//* Thread Deadlock Example in Posix *

/** * This will make your program compiled in thread-safe mode * and the library included automatically when using recent gcc * gcc -pthread program.c * * If you want just to include the library on most Unix/Linux/OS X use * gcc program.c -lpthread * * Except on Solaris where this library has a different name * gcc program.c -lpthreads */ #include <pthread.h> #include <stdlib.h> #include <stdio.h> typedef struct { unsigned long int duration; char print_debug; } parameters_t; volatile unsigned long int GlobalSum; /* data is shared by the thread(s) */ pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; void *runner1(void *param); /* the thread 1 */ void *runner2(void *param); /* the thread 2 */ int main(int argc, char *argv[]) { pthread_t tid1; /* the thread identifier */ pthread_attr_t attr1; /* set of attributes for the thread */ pthread_t tid2; /* the thread identifier */ pthread_attr_t attr2; /* set of attributes for the thread */ parameters_t ThreadParam1; parameters_t ThreadParam2; long int param; // do some basic error checking if (argc != 2) { fprintf(stderr,"Use: \"%s <DURATION>\"\n or enter the duration now\n\n" "Loop count = ", argv[0]); fscanf(stdin," %ld", &param); // <- MSVS compiler warning is irrelevant here and can be avoided } else { param = atol(argv[1]); } if (param < 0) { fprintf(stderr, "an integer >= 0 is required \n"); return -1; } ThreadParam1.duration = param; ThreadParam1.print_debug = 'x'; ThreadParam2.duration = param; ThreadParam2.print_debug = 'o'; /* get the default attributes */ pthread_attr_init(&attr1); pthread_attr_init(&attr2); /* create the threads */ // Note: pass NULL instead of attributes to use the default settings pthread_create(&tid1,&attr1,runner1,&ThreadParam1); pthread_create(&tid2,&attr2,runner2,&ThreadParam2); /* now wait for the threads to exit */ pthread_join(tid1,NULL); pthread_join(tid2,NULL); if (GlobalSum==0) fprintf(stdout,"sum = %ld\n", GlobalSum); else fprintf(stdout,"sum = %ld (Shouldn\'t it be 0\a?)\n", GlobalSum); return(0); } /** * The threads will begin control in this function */ void *runner1(void *param) { parameters_t * P = (parameters_t*) param; unsigned long int i, j; // local variables might be quicker to access and/or easier to optimize for a compiler const unsigned long int upper = P->duration; const char prn = P->print_debug; for (i = 1; i <= 1000; i++) { for (j = 1; j <= upper; j++) { pthread_mutex_lock( &mutex1 ); pthread_mutex_lock( &mutex2 ); GlobalSum++; pthread_mutex_unlock( &mutex2 ); pthread_mutex_unlock( &mutex1 ); } fprintf(stdout, "%c", prn); fflush(stdout); } pthread_exit(0); } void *runner2(void *param) { parameters_t * P = (parameters_t*) param; unsigned long int i, j; // local variables might be quicker to access and/or easier to optimize for a compiler const unsigned long int upper = P->duration; const char prn = P->print_debug; for (i = 1; i <= 1000; i++) { for (j = 1; j <= upper; j++) { pthread_mutex_lock( &mutex2 ); pthread_mutex_lock( &mutex1 ); GlobalSum--; pthread_mutex_unlock( &mutex1 ); pthread_mutex_unlock( &mutex2 ); } fprintf(stdout, "%c", prn); fflush(stdout); } pthread_exit(0); }