一、题目要求

使用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;
}
//A转给B money
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); //A 1200 B 1800
thread thb(ThreadFun, std::ref(B), std::ref(C), 500); //B 1300 C 2000
thread thc(ThreadFun, std::ref(C), std::ref(A), 300); //A 1500 C 1700

tha.join();
thb.join();
thc.join();
//A 1500 B 1300 C 1700
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); //A 1200 B 1800
thread thb(ThreadFun, std::ref(B), std::ref(C), 500); //B 1300 C 2000
thread thc(ThreadFun, std::ref(C), std::ref(A), 300); //A 1500 C 1700

tha.join();
thb.join();
thc.join();
//A 1500 B 1300 C 1700
cout << A.GetName() << ": " << A.GetMoney() << endl;
cout << B.GetName() << ": " << B.GetMoney() << endl;
cout << C.GetName() << ": " << C.GetMoney() << endl;

return 0;
}
#endif

在这里插入图片描述