#include #include #include using namespace std; #define TOTAL 200 int checking = TOTAL/2; int savings = TOTAL/2; // Using multiple locks to demonstrate deadlock pthread_mutex_t mutex_checking; pthread_mutex_t mutex_savings; // -------------------------------------------------- // Print bank statement // -------------------------------------------------- void print() { cout << "Statement:" << " checking=" << checking << " savings=" << savings << endl; } // -------------------------------------------------- // Trying to save money // -------------------------------------------------- void* saver(void* p_nb_transfers) { int nb = *((int*)p_nb_transfers); for ( int i = 0; i < nb; i++ ) { pthread_mutex_lock (&mutex_checking); int balance = checking; sleep(1); pthread_mutex_lock (&mutex_savings); savings += balance; pthread_mutex_unlock (&mutex_savings); checking = 0; pthread_mutex_unlock (&mutex_checking); print(); sleep(1); } // Can use pthread_exit to terminate a thread //pthread_exit(0); // Or can simply return from the start function of this thread return NULL; } // -------------------------------------------------- // Want to spend money // -------------------------------------------------- void* spender(void* p_nb_transfers) { int nb = *((int*)p_nb_transfers); for ( int i = 0; i < nb; i++ ) { pthread_mutex_lock (&mutex_savings); int balance = savings; sleep(1); pthread_mutex_lock (&mutex_checking); checking += balance; pthread_mutex_unlock (&mutex_checking); savings = 0; pthread_mutex_lock (&mutex_savings); print(); sleep(1); } // Can use pthread_exit to terminate a thread //pthread_exit(0); // Or can simply return from the start function of this thread return NULL; } //----------------------------------------------------------------------------- int main(int argc, char ** argv) { if ( argc < 2 ) { cerr << "Please specify number of bank account transfers to make\n"; return 0; } int nb_transfers = atoi(argv[1]); int *p_nb_transfers = &nb_transfers; pthread_mutex_init(&mutex_checking, NULL); pthread_mutex_init(&mutex_savings, NULL); pthread_t spender_thread; pthread_t saver_thread; // Create first thread int rc = pthread_create(&spender_thread, NULL, spender, (void*)p_nb_transfers); if ( rc ) { cerr << "Failed to create spender thread\n"; return 1; } // Create second thread rc = pthread_create(&saver_thread, NULL, saver, (void*)p_nb_transfers); if ( rc ) { cerr << "Failed to create saver thread\n"; return 1; } // Wait for threads to finish pthread_join(spender_thread, 0); pthread_join(saver_thread, 0); pthread_mutex_destroy(&mutex_checking); pthread_mutex_destroy(&mutex_savings); return 0; }