/* include stdio.h, stdlib.h, pthread.h */ /* specify pthread libraries during compilation, cc -lpthread ... */ int account1balance = 100 ; int account2balance = 200 ; int transferAmount = 20 ; pthread_mutex_t pm = PTHREAD_MUTEX_INITIALIZER; void L (pthread_mutex_t *tmp ) { pthread_mutex_lock(tmp); } void U (pthread_mutex_t *tmp ) { pthread_mutex_unlock(tmp); } void *first ( ) { L(&pm); account1balance -= transferAmount; U(&pm); } void *second ( ) { L(&pm); account2balance += transferAmount; U(&pm); } void main( int argc, char* argv[]){ char NL[] = "\\\n" ; pthread_t t1, t2; pthread_create( &t1, NULL, first, NULL); pthread_create( &t2, NULL, second, NULL); L(pm); printf("PreJoin:%d and %d %s", account1balance, account2balance, NL); U(pm); pthread_join( t1, NULL); pthread_join( t2, NULL); printf("After:%d and %d %s", account1balance, account2balance, NL) ; }
/* include stdio.h, stdlib.h, pthread.h */ /* specify pthread libraries during compilation, cc -lpthread ... */ pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; int x = 0 ; int y = 23; int scenario; void L (pthread_mutex_t *tmp ) { pthread_mutex_lock(tmp); } void U (pthread_mutex_t *tmp ) { pthread_mutex_unlock(tmp); } void hangaround(){ int i; for(i=0; i < 10000000; i++) ; } int f (int t) { hangaround(); return(t+1); } int g (int t) { hangaround(); return(t+1); } void *first (void* arg ) { hangaround(); switch (scenario) { case 1: { x = f(x) ; break; } case 2: { L(&m); x = f(x); U(&m); break; } case 3: { L(&m1); x = f(x); U(&m); break; } case 4: { U(&m1); x = f(x); L(&m1); break; } case 5: { L(&m); L(&m); x = f(x); U(&m); U(&m); break; } case 6: { L(&mx); L(&m); x = f(x); U(&mx); U(&m); break; } } } void *second ( void* arg) { switch (scenario) { case 1: { x = g(y); break; } case 2: { L(&m); x = g(y); U(&m); break; } case 3: { L(&m); x = g(y); U(&m1); break; } case 4: { U(&m1); x = g(y); L(&m1); break; } case 5: { L(&m); x = g(y); U(&m); break; } case 6: { L(&m); L(&mx); x = g(y); U(&m); U(&mx); break; } } } void main( int argc, char* argv[] ){ pthread_t t1, t2; if (argc != 2) { printf("Usage: %s scenarioNumber(1-6) n", argv[0]); } else { scenario = atoi(argv[1]); } pthread_create( &t2, NULL, second, NULL); pthread_create( &t1, NULL, first, NULL); pthread_join( t1, NULL); pthread_join( t2, NULL); printf ("scenario %d : x = %d \n", scenario, x); }
/* include stdio.h, pthread.h, semaphore.h */ /* specify pthread and semaphore libraries during compilation */ /* POSIX Semaphore implementation may not be available */ sem_t m, m1, mx; int x = 0 ; int y = 23; int scenario; void P (sem_t *s ) { sem_wait(s); } void V (sem_t *s ) { sem_post(s); } void *first ( void* arg) { switch (scenario) { case 1: { x = x + 1; break; } case 2: { P(&m); x = x + 1; V(&m); break; } case 3: { P(&m1); x = x + 1; V(&m); break; } case 4: { V(&m1); x = x + 1; P(&m1); break; } case 5: { P(&mx); P(&m); x = x + 1; V(&mx); V(&m); break; } } } void *second (void* arg ) { switch (scenario) { case 1: { x = y + 1; break; } case 2: { P(&m); x = y + 1; V(&m); break; } case 3: { P(&m); x = y + 1; V(&m1); break; } case 4: { V(&m1); x = y + 1; P(&m1); break; } case 5: { P(&m); P(&mx); x = y + 1; V(&m); V(&mx); break; } } } void main( char* argv[], int argc){ pthread_t t1, t2; if (argc != 2) { printf("Usage: %s scenarioNumber(1-5)\n", argv[0]); } else { scenario = atoi(argv[1]) ; } sem_init(&m, 0, 1); /* initialize to 1 */ sem_init(&m1, 0, 0); /* initialize to 0 */ sem_init(&mx, 0, 1); /* initialize to 1 */ pthread_create( &t1, NULL, first, NULL); pthread_create( &t2, NULL, second, NULL); pthread_join( t1, NULL); pthread_join( t2, NULL); printf ("scenario %d : x = %d \n", scenario, x); }
Assume the program has three threads, namely a main thread, a producer thread, and a consumer thread. The main thread is responsible for creating the other threads and properly terminating the program.