#include #include #include using namespace std; #define TOTAL 10000 #define TRANSFER 100 int checking = TOTAL/2; int savings = TOTAL/2; // The mutex that we will use to lock access to the bank accounts pthread_mutex_t mutex_bank; // -------------------------------------------------- // 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_bank); // Read balance for each account int old_savings = savings; int old_checking = checking; // Update balance for each account savings = old_savings + TRANSFER; if ( i % 3 ) { sleep(1); } checking = old_checking - TRANSFER; print(); pthread_mutex_unlock (&mutex_bank); 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_bank); // Read balance for each account int old_checking = checking; int old_savings = savings; // Update balance for each account checking = old_checking + TRANSFER; if ( i % 2 ) { sleep(1); } savings = old_savings - TRANSFER; print(); pthread_mutex_unlock (&mutex_bank); 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; // Initialize the mutex pthread_mutex_init(&mutex_bank, 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, NULL); pthread_join(saver_thread, NULL); // Destory the mutex pthread_mutex_destroy(&mutex_bank); return 0; }