/*! Synchronization example with monitor on "old bridge" problem */ #include #include #include #include #define THREADS 20 /* mutex and conditional variables, statically initialized */ static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t s_n = PTHREAD_COND_INITIALIZER; static pthread_cond_t n_s = PTHREAD_COND_INITIALIZER; static pthread_cond_t *cq[2] = {&s_n, &n_s}; struct CarInfo { int id; int dir; }; static char *sdir[] = {"south", "north"}; static int cars_on_bridge = 0; static int dir_on_bridge = -1; /* 0: S->N; 1:N->S; -1:bridge empty */ void *car_thread(void *p) { struct CarInfo *car = p; struct timespec t = {5, 0}; pthread_mutex_lock(&m); while (cars_on_bridge > 2 || (dir_on_bridge != -1 && dir_on_bridge != car->dir)) pthread_cond_wait(cq[car->dir], &m); cars_on_bridge++; dir_on_bridge = car->dir; printf("Car %2d on bridge, going %s, on bridge %d car(s) (to %s)\n", car->id, sdir[car->dir], cars_on_bridge, sdir[dir_on_bridge]); pthread_mutex_unlock(&m); nanosleep(&t, NULL); pthread_mutex_lock(&m); cars_on_bridge--; printf("Car %2d off bridge, going %s, on bridge %d car(s) (to %s)\n", car->id, sdir[car->dir], cars_on_bridge, sdir[dir_on_bridge]); if (cars_on_bridge > 0) { pthread_cond_signal(cq[car->dir]); } else { dir_on_bridge = -1; pthread_cond_broadcast(cq[1 - car->dir]); } pthread_mutex_unlock(&m); free(car); return NULL; } int main() { pthread_t thr_id; pthread_attr_t attr; int i; struct CarInfo *car; struct timespec t = {2, 0}; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); for (i = 0; i < THREADS; i++) { car = malloc(sizeof(struct CarInfo)); car->id = i+1; car->dir = rand() & 1; printf( "New car %d arrived from %s\n", i+1, sdir[1 - car->dir]); pthread_create(&thr_id, &attr, car_thread, (void *) car); nanosleep(&t, NULL); } return 0; } /* Example run: $ gcc pthread_mutex.c -pthread -Wall $ ./a.out New car 1 arrived from south Car 1 on bridge, going north, on bridge 1 car(s) (to north) New car 2 arrived from north New car 3 arrived from south Car 3 on bridge, going north, on bridge 2 car(s) (to north) Car 1 off bridge, going north, on bridge 1 car(s) (to north) New car 4 arrived from south Car 4 on bridge, going north, on bridge 2 car(s) (to north) New car 5 arrived from south Car 5 on bridge, going north, on bridge 3 car(s) (to north) Car 3 off bridge, going north, on bridge 2 car(s) (to north) New car 6 arrived from south Car 6 on bridge, going north, on bridge 3 car(s) (to north) Car 4 off bridge, going north, on bridge 2 car(s) (to north) New car 7 arrived from north Car 5 off bridge, going north, on bridge 1 car(s) (to north) New car 8 arrived from north Car 6 off bridge, going north, on bridge 0 car(s) (to north) Car 2 on bridge, going south, on bridge 1 car(s) (to south) ... */