实现银行转账的死锁
#include <mutex>
#include <iostream>
#include <thread>
#include <condition_variable>
using namespace std;
mutex mxA;
mutex mxB;
int countA = 1000;
int countB = 1000;
void thread_func1(int money) //A---> B转账money元
{
//实现A给B账户转账 那么先对A上锁
unique_lock<mutex> lcA(mxA);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));//睡眠,保证线程1获得A账户的锁
cout << "线程1获得了A账户的锁" << endl;
if (countA > money)//满足转账要求
{
cout << "线程1请求B账户的锁子" << endl;
unique_lock<mutex> lcB(mxB);//申请转账对象B的锁
countA -= money;
countB += money;
cout << "转账成功A------>B:" << money << endl;
}
else//不满足转账要求
{
cout << "A账户余额不足" << endl;
}
}
void thread_func2(int money) //B----->A转账money元
{
//实现B给A账户转账 那么先对B上锁
unique_lock<mutex> lcB(mxB);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));//睡眠,保证线程2获得B账户的锁
cout << "线程2获得了B账户的锁" << endl;
if (countB > money)//满足转账要求
{
cout << "线程2请求A账户的锁子" << endl;
unique_lock<mutex> lcA(mxA);//申请转账对象A的锁
countB -= money;
countA += money;
cout << "转账成功B----->A:" << money << endl;
}
else//不满足转账要求
{
cout << "B账户余额不足" << endl;
}
}
int main()
{
thread s1(thread_func1, 100);
thread s2(thread_func2, 200);
s1.join();
s2.join();
return 0;
}
运行截图如下
解决银行死锁问题
分析死锁产生的四个条件
1.互斥
2.占有且等待。
3.不可抢占
4.循环等待
只要打破一个条件,即可解决上诉问题
方法:打破占有且等待 即只有持有所有资源的线程才可以直接进行操作。
#include <mutex>
#include <iostream>
#include <thread>
#include <condition_variable>
#include <set>
#include <unordered_set>
using namespace std;
mutex mx;
condition_variable cv;
class Count//账户类
{
public:
Count(int m) : money(m) {}
~Count() = default;
bool operator<(const Count& src)const { return money < src.money; }
int getMoney() { return money; }
void setMoney(int m) { money = m; }
private:
int money;//现有的资产
};
class Account//管理类
{
public:
~Account() = default;
static Account* getInstance()//初始化构建
{
static Account a;
return &a;
}
void apply(Count& A, Count& B)//添加函数
{
unique_lock<mutex> lc(mx);//申请加锁
while (s.count(A) > 0 || s.count(B) > 0)
{
cv.wait(lc); //阻塞等待,挂起
}
s.insert(A);//插入A资源
s.insert(B);//插入B资源
}
void free(Count&A, Count& B)//释放函数
{
unique_lock<mutex> lc(mx);//申请加锁
s.erase(A);//删除A资源
s.erase(B);//删除B资源
cv.notify_all();//唤醒所有线程
}
private:
Account() = default;
Account(const Account& src) = delete;
//删除缺省的拷贝构造函数
Account& operator=(const Account& src) = delete;
//删除缺省的=函数
set<Count> s;//每一组值都是唯一的!!!
};
void thread_func1(Count& A, Count& B, int money) //A--->B转账money元
{
Account* acc = Account::getInstance();//初始化
acc->apply(A, B);//把A,B资源传入,调用
if (A.getMoney() >= money)//满足转账要求
{
A.setMoney(A.getMoney() - money);//转账
B.setMoney(B.getMoney() + money);//进账
cout << "successful:" << endl;//打印“成功”
cout << money << endl;//打印转账的金额数
}
else//不满足转账要求
{
cout << "余额不足" << endl;
}
acc->free(A, B);//释放资源
}
int main()
{
Count A(1000);//创建A账户并初始化其账户值为1000元
Count B(2000);//创建B账户并初始化其账户值为2000元
thread s1(thread_func1, ref(A), ref(B), 300);
//A----->B 300 A给B转300元
thread s2(thread_func1, ref(B), ref(A), 100);
//B----->A 100 B给A转100元
s1.join();
s2.join();
cout << "A现在的账户上的值为:" << A.getMoney() << endl;
cout << "B现在的账户上的值为:" << B.getMoney() << endl;
return 0;
}
运行截图如下