/* Bruce A. Maxwell Fall 2012 CS 333 An example of a race condition if the code does not use mutex locks. gcc -o mutexsimple mutex-simple.c -lpthread */ #include #include #include #include void *fcounter(void *); void *fbad(void *); int counter = 0; // data structure passed to the thread functions typedef struct { pthread_mutex_t mutex; int id; } threadInfo; // main: expects "bad" or "good" on the command line int main(int argc, char *argv[]) { int i; pthread_mutex_t mutex; pthread_t thread[4]; threadInfo ti[4]; int usebad; if( argc < 2 ) { printf("usage: %s \n", argv[0]); return(-1); } // which function to run usebad = !strcmp( "bad", argv[1] ) ? 1 : 0; // init mutex pthread_mutex_init( &(mutex), NULL ); // spawn three threads for(i=0;i<4;i++) { ti[i].id = i; ti[i].mutex = mutex; if( usebad ) pthread_create( &(thread[i]), NULL, fbad, &(ti[i]) ); else pthread_create( &(thread[i]), NULL, fcounter, &(ti[i]) ); } // wait until both are done (join) for(i=0;i<4;i++) { pthread_join( thread[i], NULL ); } // destroy mutex pthread_mutex_destroy( &(mutex) ); return(0); } // Increment a global counter variable // This function uses mutex locks void *fcounter( void *userdata ) { int i; threadInfo *ti = (threadInfo *)userdata; for(i=0;i<3;i++) { pthread_mutex_lock( &(ti->mutex) ); // P(s) counter++; printf("%d counter is %d\n", ti->id, counter ); pthread_mutex_unlock( &(ti->mutex) ); // V(s) usleep( rand() % 10 ); } return( NULL ); } // Increment a global counter variable // This function does not use mutex locks void *fbad( void *userdata ) { int i; threadInfo *ti = (threadInfo *)userdata; for(i=0;i<3;i++) { counter++; usleep( rand() % 10 ); printf("%d counter is %d\n", ti->id, counter ); } return( NULL ); }