/* File: ~liux/public_html/cop460/examples/simple-mutex.cc Purpose: Demonstrate how to synchronize multiple threads using mutual exclusion locks Author: Xiuwen Liu On the web: http://www.cs.fsu.edu/~liux/cop460/examples/simple-mutex.cc Command to complie (Pay attention to -lthread): g++ -o simple-mutex simple-mutex.cc -lthread */ #include #include #include #include #include #include #include #include #include #define NUM_THREADS 5 thread_t tid[NUM_THREADS]; /* array of thread IDs */ int totalTransaction; int accounts[NUM_THREADS]; /* Account balances */ int performed_transactions[NUM_THREADS]; void * RandomTransaction(void *msg); int PerformATransaction(int from, int to, int val); int CheckRunning(void); mutex_t exclusive_mutex; int main(int argc, char *argv[]) { int i, sum; // Initialize mutex lock mutex_init(&exclusive_mutex, USYNC_THREAD, (void *)NULL); totalTransaction = 0; for (i=0; i < NUM_THREADS; i++) { accounts[i] = 1000; performed_transactions[i] = 0; } sum =0; for (i=0; i<5; i++) { cout << "\n\tInit account " << i+1 << "'s balance: " << accounts[i]; sum += accounts[i]; } cout <<"\n\tTotal initial balance is " << sum << endl; for (i=0; i < NUM_THREADS; i++) { if (thr_create(NULL, (int)0, RandomTransaction, (char *)NULL, THR_SUSPENDED, &(tid[i])) <0) { perror("create thread: "); return -1; } } for (i=0; i < NUM_THREADS; i++) thr_continue(tid[i]); while (thr_join((unsigned int)NULL, (unsigned int *)NULL, (void **)NULL) == 0); mutex_destroy(&exclusive_mutex); for (i=0; i < NUM_THREADS; i++) { cout << "\nAccount " << i+1 << " performed " << performed_transactions[i]; } cout << "\n"; return 0; } void * RandomTransaction(void *msg) { thread_t current_thr; int myAcct, toAcct; int amount; current_thr = thr_self(); for (myAcct=0; myAcct < NUM_THREADS; myAcct++) { if (current_thr == tid[myAcct]) break; } if (myAcct >= NUM_THREADS) { cerr << "Something must be wrong with the thread IDs.\n"; return (void *)NULL; } cout << "Thread " << myAcct+1 << " is running.\n"; do { /* First figure out my account number */ do { toAcct = ((int)random())%NUM_THREADS; } while (myAcct == toAcct); amount = (int)(random()%10+10); PerformATransaction(myAcct, toAcct, amount); } while(CheckRunning()); return (void *)NULL; } int PerformATransaction(int from, int to, int val) { int i, sum; if (accounts[from] < val) { thr_yield(); return -1; } performed_transactions[from]++; mutex_lock(&exclusive_mutex); accounts[from] -= val; thr_yield(); accounts[to] += val; totalTransaction++; if ((totalTransaction %1000000) == 0) { sum =0; cout << "\nNow " << totalTransaction << " transactions have been completed."; for (i=0; i<5; i++) { cout << "\n\tAccount " << i+1 << "'s balance: " << accounts[i]; sum += accounts[i]; } cout << "\n\tTotal balance after " << totalTransaction << " transactions is " << sum << endl; } mutex_unlock(&exclusive_mutex); return 0; } int CheckRunning(void) { int i; mutex_lock(&exclusive_mutex); i = (int)(totalTransaction < 10000000); mutex_unlock(&exclusive_mutex); return i; }