C++/Thread mutex question
Expert: vijayan - 1/1/2009
QuestionQUESTION: Dear vijayan,
I know this question is not related to your field but I figured you may be able to help me on this still.
Using synchronization with mutexes, I need to come up with a program that solves the traffic light problem. If there is a car passing it should lock the mutex and unlock it when it's passed. If the light is red and there is no car passing it should remain red otherwise it should turn green after a minimum number of seconds.
I tried searching on line for some tutorials on threads and mutex but couldn't find anything that helpful.
You are truly my favorite export on this website so that is why I am writing to you.
I thank you for your help or advice in advance.
ANSWER: the current c++ standard (c++98) has no library support for threads; you have to rely on threading support provided by the native platform. each OS provides its own set of libraries for handling multiple threads. the resulting code is not only non-standard, but also non-portable.
however, there is good news: standard C++ threads are imminent in c++09. these are adapted from the portable thread support provided by the boost libraries.
http://www.boost.org/
http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html
see these tutorials on using boost threads:
http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html
http://paulbridger.net/mutexes
here is a trivial program to illustrate the use of boost threads and mutexes
//************************************************************
//
// link with the boost thread library
// eg. with gcc on freebsd:
// g++ -Wall -std=c++98 -pedantic -Werror -lboost_thread -I /usr/local/include -L /usr/local/lib sync.cc
//
//************************************************************
#include <boost/thread.hpp>
#include <unistd.h> // sleep (posix)
#include <ctime>
#include <cstdlib>
#include <iostream>
// traffic light state
enum colour { GREEN, RED } ;
colour light_colour = GREEN ;
// mutex to synchronize access to traffic light
boost::mutex traffic_light_mutex ;
// thread to turn red light on/off
void light_timer_thread()
{
enum { GREEN_TIME = 5, RED_TIME = 2, NUM_SWITCHES = 1024*1024 } ;
for( int i = 0 ; i < NUM_SWITCHES ; ++i )
{
// turn light to red
{
// get exclusive ownership of mutex (wait for car to pass)
boost::mutex::scoped_lock lock_it( traffic_light_mutex ) ;
// ok, now we have exclusive access to the light
std::cout << "red..." << std::flush ;
light_colour = RED ; // set light to red
sleep( RED_TIME ) ; // wait for RED_TIME seconds
std::cout << "green" << std::endl ;
// destructor for lock_it will release the mutex
}
light_colour = GREEN ; // set light to green
sleep( GREEN_TIME ) ; // wait for GREEN_TIME seconds
}
}
void a_car_passing_thread() // manage passing of a car
{
enum { CAR_PASS_TIME = 1 } ;
// get exclusive ownership of mutex (wait for light to tuen green)
boost::mutex::scoped_lock lock_it( traffic_light_mutex ) ;
// ok, now we have exclusive access to the light
std::cout << "passing car..." << std::flush ;
sleep( CAR_PASS_TIME ) ; // wait for CAR_PASS_TIME seconds
std::cout << "passed" << std::endl ;
// destructor for lock_it will release the mutex
}
int main()
{
std::srand( unsigned( std::time(0) ) ) ;
// create a timer thread - turn light green->red->green
boost::thread timer_thread( &light_timer_thread ) ;
enum { MAX_CAR_ARRIVE_TIME = 5, NUM_CARS = 1024 } ;
// simulate passing of cars every 0 - MAX_CAR_ARRIVE_TIME secs
for( int i = 0 ; i < NUM_CARS ; ++i )
{
sleep( std::rand() % MAX_CAR_ARRIVE_TIME ) ; // wait for a car to arrive
boost::thread car_thread( &a_car_passing_thread ) ; // let the car pass
}
timer_thread.join() ; // wait for timer_thread to finish
}
if you want to program using the native os thread support, here are a few links.
posix threads tutorials:
https://computing.llnl.gov/tutorials/pthreads/
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
windows threads tutorial:
http://faq.programmerworld.net/programming/win32-multithreading-and-synchronizat
---------- FOLLOW-UP ----------
QUESTION: thanks for your quick reply as usual.
I forgot to mention that this I needed help with C language on this issue and not c++ and that's why I said it was not related.
In terms of OS, I need to run it on linux.
Your suggestion or help would be MUCH appreciated.
thank you so much again.
ANSWER: ok. read these pthread tutorials first.
https://computing.llnl.gov/tutorials/pthreads/
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
and then see if you can understand what this program does. it is an almost verbatim translation of the earlier program (with posix threads and C instead of boost threads and C++).
/************************************************************
*
* link with the pthread library
* eg. with gcc
* gcc -Wall -std=c89 -pedantic -Werror -lpthread use_pthread.c
*
*************************************************************/
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
enum colour { GREEN, RED } ; /* traffic light state */
int light_colour = GREEN ;
/* mutex to synchronize access to traffic light */
pthread_mutex_t traffic_light_mutex = PTHREAD_MUTEX_INITIALIZER ;
/* thread to turn red light on/off */
void* light_timer_thread( void* arg )
{
enum { GREEN_TIME = 5, RED_TIME = 2, NUM_SWITCHES = 1024*1024 } ;
int i ;
for( i = 0 ; i < NUM_SWITCHES ; ++i )
{
/* turn light to red */
{
/* get exclusive ownership of mutex (wait for car to pass) */
pthread_mutex_lock( &traffic_light_mutex ) ;
/* ok, now we have exclusive access to the light */
printf( "red..." ) ;
fflush( stdout ) ;
light_colour = RED ; /* set light to red */
sleep( RED_TIME ) ; /* wait for RED_TIME seconds */
puts( "green" ) ;
fflush( stdout ) ;
/* release the mutex */
pthread_mutex_unlock( &traffic_light_mutex ) ;
}
light_colour = GREEN ; /* set light to green */
sleep( GREEN_TIME ) ; /* wait for GREEN_TIME seconds */
}
return NULL ;
}
void* a_car_passing_thread( void* arg ) /* manage passing of a car */
{
enum { CAR_PASS_TIME = 1 } ;
/* get exclusive ownership of mutex (wait for light to tuen green) */
pthread_mutex_lock( &traffic_light_mutex ) ;
/* ok, now we have exclusive access to the light */
printf( "passing car..." ) ;
fflush( stdout ) ;
sleep( CAR_PASS_TIME ) ; /* wait for CAR_PASS_TIME seconds */
puts( "passed" ) ;
fflush( stdout ) ;
/* release the mutex */
pthread_mutex_unlock( &traffic_light_mutex ) ;
return NULL ;
}
int main()
{
pthread_t timer_thread ;
int i ;
enum { MAX_CAR_ARRIVE_TIME = 5, NUM_CARS = 1024 } ;
srand( (unsigned)time( NULL ) ) ;
/* create a timer thread - turn light green->red->green */
pthread_create( &timer_thread, NULL, &light_timer_thread, NULL ) ;
/* simulate passing of cars every 0 - MAX_CAR_ARRIVE_TIME secs */
for( i = 0 ; i < NUM_CARS ; ++i )
{
pthread_t car_thread ;
sleep( rand() % MAX_CAR_ARRIVE_TIME ) ; /* wait for a car to arrive */
pthread_create( &car_thread, NULL, &a_car_passing_thread, NULL ) ;
}
pthread_join( timer_thread, NULL ) ; /* wait for timer_thread to finish */
return 0 ;
}
---------- FOLLOW-UP ----------
QUESTION: Dear vijayan,
thank you SO MUCH for your reply. I am getting the following error messages when trying to compile and execute
it. could you tell me what could the problem be please?
thank you in advance.
naji@naji-laptop:~/Documents/Linux_Shit/Mutex$ gcc -Wall -std=c89 -pedantic -Werror -lpthread mutex.c
naji@naji-laptop:~/Documents/Linux_Shit/Mutex$ gcc -o mutex mutex.c
/tmp/ccuzrCvJ.o: In function `main':
mutex.c:(.text+0x145): undefined reference to `pthread_create'
mutex.c:(.text+0x1ad): undefined reference to `pthread_create'
mutex.c:(.text+0x1cd): undefined reference to `pthread_join'
collect2: ld returned 1 exit status
Answerglad you could solve this yourself by realizing that you need to link with libpthread.
ideally, you should also be calling pthread_mutex_destroy to free the mutex object once it is no longer needed. in this toy program, we are returning from main immediately (which does an orderly termination of the process) and all system resources held by the process are released automatically.