一、题目要求
使用C++的线程并发库,实现并模拟多人在线同时转账的过程,确保转账不能出现差错。
例如:
Account A(“xiaoming”, 1000);
Account B(“zhangqiang”, 2000);
Account C(“zq”, 1500);
B->A 200 A 1200 B 1800
B->C 500 B 1300 C 2000
C->A 300 A 1500 C 1700
二、代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| #if 1 #include<iostream> #include<mutex> #include<condition_variable> #include<map> using namespace std;
std::mutex mtx; std::condition_variable cv;
class Account { public: Account() :name(), money(0) {} Account(const string& na, int my) : name(na), money(my) {} ~Account() = default; const int GetMoney() const { return money; } void SetMoney(int m) { money = m; } const string& GetName()const { return name; } private: string name; int money; };
class Bank { public: ~Bank() {} static Bank& GetSingleBank() { return bank; } void TransAccounts(Account& A, Account& B) { unique_lock<mutex> lock(mtx); while (map.count(A.GetName()) > 0 || map.count(B.GetName()) > 0) { cv.wait(lock); } map[A.GetName()] = A.GetMoney(); map[B.GetName()] = B.GetMoney(); } void ClearAccount(Account& A, Account& B) { unique_lock<mutex> lcok(mtx); map.erase(A.GetName()); map.erase(B.GetName()); cv.notify_all(); } private: Bank() = default; Bank& operator=(const Bank& b) = delete; static Bank bank;
std::map<string, int> map; };
Bank Bank::bank;
void ThreadFun(Account& A, Account& B, int money) { if (money <= 0) return; Bank& bank = Bank::GetSingleBank(); bank.TransAccounts(A, B); if (A.GetMoney() >= money) { A.SetMoney(A.GetMoney() - money); B.SetMoney(B.GetMoney() + money); } else { cout << A.GetName() << "->" << B.GetName() << "交易失败" << endl; } bank.ClearAccount(A, B); }
int main() { Account A("xiaoming", 1000); Account B("zhangqiang", 2000); Account C("zq", 1500); thread tha(ThreadFun, std::ref(B), std::ref(A), 200); thread thb(ThreadFun, std::ref(B), std::ref(C), 500); thread thc(ThreadFun, std::ref(C), std::ref(A), 300);
tha.join(); thb.join(); thc.join(); cout << A.GetName() << ": "<< A.GetMoney()<< endl; cout << B.GetName() << ": "<< B.GetMoney()<< endl; cout << C.GetName() << ": " << C.GetMoney() << endl; return 0; } #endif
|
三、使用线程并发库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include<iostream> #include<mutex> using namespace std;
class Account { public: Account() :name(), money(0) {} Account(const string& na, int my) : name(na), money(my) {} ~Account() = default; const int GetMoney() const { return money; } void SetMoney(int m) { money = m; } const string& GetName()const { return name; } private: string name; int money; };
#if 1 mutex mtx1; mutex mtx2; void ThreadFun(Account& A, Account& B, int money) { unique_lock<mutex> lock1(mtx1, defer_lock); unique_lock<mutex> lock2(mtx2, defer_lock); lock(lock1, lock2);
if (A.GetMoney() >= money) { A.SetMoney(A.GetMoney() - money); B.SetMoney(B.GetMoney() + money); } }
int main() { Account A("xiaoming", 1000); Account B("zhangqiang", 2000); Account C("zq", 1500); thread tha(ThreadFun, std::ref(B), std::ref(A), 200); thread thb(ThreadFun, std::ref(B), std::ref(C), 500); thread thc(ThreadFun, std::ref(C), std::ref(A), 300);
tha.join(); thb.join(); thc.join(); cout << A.GetName() << ": " << A.GetMoney() << endl; cout << B.GetName() << ": " << B.GetMoney() << endl; cout << C.GetName() << ": " << C.GetMoney() << endl;
return 0; } #endif
|