//OPT: -lpthread #include #include #include #include #include using namespace std; using namespace std::chrono; class bankaccount { public: bankaccount() { bal = 0; numchecks = 0; } void deposit(int amt) { lock_guard L(m); // only operation on lock_guard is constructor (and destructor) int currbal = bal; this_thread::sleep_for(milliseconds(1)); bal = currbal + amt; } void withdraw(int amt) { lock_guard L(m); int currbal = bal; this_thread::sleep_for(milliseconds(1)); bal = currbal - amt; } void writecheck(int amt) { unique_lock Lamt(m,defer_lock); unique_lock Lchk(m2,defer_lock); // Lamt.lock(); Lchk.lock(); -- bad -- could be ordering problem std::lock(Lamt,Lchk); bal -= amt; numchecks--; } void printchecks() { unique_lock Lamt(m,defer_lock); unique_lock Lchk(m2,defer_lock); std::lock(Lamt,Lchk); numchecks += 50; bal -= 1000; // 50 checks cost ten dollars } int balance() { return bal; } int nchecks() { return numchecks; } private: mutex m; int bal; // in cents mutex m2; int numchecks; }; void earner(bankaccount &a) { a.deposit(1000); // add ten dollars a.deposit(1000); // add ten dollars a.printchecks(); a.deposit(1000); // add ten dollars a.deposit(1000); // add ten dollars } void spender(bankaccount &a) { a.withdraw(800); // spend eight dollars a.writecheck(200); // write check for 2 dollars a.withdraw(800); // spend eight dollars a.withdraw(800); // spend eight dollars } int main(int argc, char **argv) { bankaccount acct; thread t1(earner,ref(acct)); thread t2(spender,ref(acct)); t1.join(); t2.join(); cout << "balance = " << acct.balance() << endl; cout << "numchecks = " << acct.nchecks() << endl; }