一、题目要求
使用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
二、代码实现
#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
三、使用线程并发库
#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
|