/* example of race condition between threads updating shared variable For simplicity, the program terminates via exit (), timeout, or via a killing signal from the user. This version uses one mutex to ensure mutual exclusion. */ #define _XOPEN_SOURCE 500 #define _REENTRANT #include #include #include #include #include #include #include #include #include #include #include #define TOTAL 1000000000 volatile long A = 500000000; volatile long B = 500000000; volatile long count_1 = 0; volatile long count_2 = 0; pthread_mutex_t M; /* why do we specify the attribute "volatile" above and below? */ void transfer (int amount, volatile long *from_account, volatile long *to_account) { *to_account = *to_account + amount; *from_account = *from_account - amount; } void handler (int sig) { fprintf (stderr, "exiting due to signal %d\n", sig); fprintf (stderr, "count_1 = %ld10 count_2 = %ld10\n", count_1, count_2); exit (-1); } void check_consistency () { long total; total = A + B; if (total != TOTAL) { fprintf (stderr, "*** LOSS OF CONSISTENCY ***\n"); fprintf (stderr, "main: A = %ld10 B = %ld10 TOTAL-(A+B) = %ld10\n", A, B, TOTAL - total); fprintf (stderr, "count_1 = %ld10 count_2 = %ld10\n", count_1, count_2); exit (-1); } } void * thread_body (void *arg) { while (1) { count_2++; pthread_mutex_lock (&M); transfer (10, &B, &A); check_consistency (); pthread_mutex_unlock (&M); } return (void *) NULL; } int main (int argc, char **argv) { pthread_attr_t attrs; pthread_t thread; struct sigaction act; /* install handler for alarm signal */ sigaction (SIGALRM, NULL, &act); act.sa_handler = handler; sigaction (SIGALRM, &act, NULL); alarm (10); /* will kill entire process in 10 seconds */ pthread_setconcurrency (2); pthread_mutex_init (&M, NULL); pthread_attr_init (&attrs); /* use the default attributes */ /* create thread */ pthread_create ( &thread, /* place to store the id of new thread */ &attrs, /* thread creation attributes */ thread_body, /* function for thread to execute */ NULL); /* pass no parameter */ while (1) { count_1++; pthread_mutex_lock (&M); transfer (10, &A, &B); check_consistency (); pthread_mutex_unlock (&M); } pthread_mutex_destroy (&M); exit (0); }