/* File: ~liux/public_html/cop460/examples/simple-semaphore.cc Purpose: Demonstrate how to synchronize multiple threads using semaphores Author: Xiuwen Liu On the web: http://www.cs.fsu.edu/~liux/cop460/examples/simple-semaphore.cc Command to complie (Pay attention to -lthread -lc): g++ -o simple-mutex simple-mutex.cc -lthread -lc */ #include #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); sema_t exclusive_sema; int main(int argc, char *argv[]) { int i, sum; // Initialize mutex lock sema_init(&exclusive_sema, (int)1, 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); sum = 0; for (i=0; i<5; i++) { cout << "\n\tFinal account " << i+1 << "'s balance: " << accounts[i]; sum += accounts[i]; } cout <<"\nTotal final balance is " << sum << endl; sema_destroy(&exclusive_sema); 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]++; sema_wait(&exclusive_sema); accounts[from] -= val; thr_yield(); accounts[to] += val; totalTransaction++; if ((totalTransaction %10000) == 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; } sema_post(&exclusive_sema); return 0; } int CheckRunning(void) { int i; sema_wait(&exclusive_sema); i = (int)(totalTransaction < 100000); sema_post(&exclusive_sema); return i; }