死锁示例
std::mutex mx1;
std::mutex mx2;
void thread_func1()
{
unique_lock<std::mutex> lc1(mx1);
cout << "1号锁" << endl;
std::this_thread::sleep_for(std::chrono::microseconds(200));
unique_lock<std::mutex> lc2(mx2);
cout << "2号锁" << endl;
}
void thread_func2()
{
unique_lock<std::mutex> lc2(mx2);
cout << "2号锁" << endl;
std::this_thread::sleep_for(std::chrono::microseconds(200));
unique_lock<std::mutex> lc1(mx1);
cout << "1号锁" << endl;
}
int main()
{
thread tha(thread_func1);
thread thb(thread_func2);
tha.join();
thb.join();
return 0;
}
std::mutex mxA;
std::mutex mxB;
int countA = 1000;
int countB = 1000;
void thread_func1(int money)
{
unique_lock<std::mutex> lcA(mxA);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
cout << "线程1获得了A账户的锁" << endl;
if (countA > money)
{
cout << "线程1请求B账户的锁子" << endl;
unique_lock<std::mutex> lcB(mxB);
countA -= money;
countB += money;
cout << "转账成功A------->B:" << money << endl;
}
else
{
cout << "A账户的余额不足" << endl;
}
}
void thread_func2(int money)
{
unique_lock<std::mutex> lcB(mxA);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
cout << "线程2获得了B账户的锁" << endl;
if (countA > money)
{
cout << "线程2请求A账户的锁子" << endl;
unique_lock<std::mutex> lcA(mxB);
countB -= money;
countA += money;
cout << "转账成功B------->A:" << money << endl;
}
else
{
cout << "B账户的余额不足" << endl;
}
}
int main()
{
thread tha(thread_func1, 200);
thread thb(thread_func2, 300);
tha.join();
thb.join();
return 0;
}
如何解决死锁
std::mutex mx;
condition_variable cv;
class Count
{
private:
int money;
public:
Count(int m) :money(m)
{}
~Count() {}
bool operator<(const Count& src) const
{
return money < src.money;
}
int GetMoney()const { return money; }
void SetMoney(int m) { money = m; }
};
class Account
{
public:
~Account() = default;
static Account& getInstance()
{
return acc;
}
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);
s.insert(B);
}
void free(Count& A, Count& B)
{
unique_lock<mutex> lc(mx);
s.erase(A);
s.erase(B);
cv.notify_all();
}
private:
Account() = default;
Account(const Account&) = delete;
Account& operator=(const Account&) = delete;
std::set<Count> s;
static Account acc;
};
Account Account::acc;
void thread_func(Count& A, Count& B, int money)
{
Account& acc = Account::getInstance();
acc.apply(A, B);
if (A.GetMoney() >= money)
{
A.SetMoney(A.GetMoney() - money);
B.SetMoney(B.GetMoney() + money);
cout << "success ful" << endl;
cout << money << endl;
}
else
{
cout << "余额不足" << endl;
}
acc.free(A, B);
}
int main()
{
Count A(5000);
Count B(1000);
Count C(3000);
Count D(4000);
std::thread thra(thread_func, std::ref(A), std::ref(B), 500);
std::thread thrb(thread_func, std::ref(B), std::ref(C), 300);
std::thread thrc(thread_func, std::ref(C), std::ref(A), 500);
std::thread thrd(thread_func, std::ref(D), std::ref(A), 300);
thra.join();
thrb.join();
thrc.join();
thrd.join();
cout << "A: " << A.GetMoney() << endl;
cout << "B: " << B.GetMoney() << endl;
cout << "C: " << C.GetMoney() << endl;
cout << "D: " << D.GetMoney() << endl;
}
我们定义了一个集合,并且在转账的过程中,要求把两个账户共同写入进去,并且进入等待队列的条件就是集合中存在两个账户
下面是使用map解决原先代码中使用set排序,导致同一个账户在insert的过程中不断的变化继而导致线程的不安全
std::mutex mx;
condition_variable cv;
class Count
{
private:
string name;
int money;
public:
Count() :name(), money(0) {}
Count(string n,int m) :name(n),money(m) {}
~Count() {}
string& getName() { return name; }
int GetMoney()const { return money; }
void SetMoney(int m) { money = m; }
};
class Account
{
public:
~Account() = default;
static Account& getInstance()
{
return acc;
}
void apply(Count& A, Count& B)
{
unique_lock<mutex> lc(mx);
while (s.count(A.getName()) > 0 || s.count(B.getName()) > 0)
{
cv.wait(lc);
}
s[A.getName()] = A;
s[B.getName()] = B;
}
void free(Count& A, Count& B)
{
unique_lock<mutex> lc(mx);
s.erase(A.getName());
s.erase(B.getName());
cv.notify_all();
}
private:
Account() = default;
Account(const Account&) = delete;
Account& operator=(const Account&) = delete;
std::map<string,Count> s;
static Account acc;
};
Account Account::acc;
void thread_func(Count& A, Count& B, int money)
{
Account& acc = Account::getInstance();
acc.apply(A, B);
if (A.GetMoney() >= money)
{
A.SetMoney(A.GetMoney() - money);
B.SetMoney(B.GetMoney() + money);
cout << "success ful" << endl;
cout << money << endl;
}
else
{
cout << "余额不足" << endl;
}
acc.free(A, B);
}
int main()
{
Count A("zyq",5000);
Count B("cbq",1000);
Count C("hxm",3000);
Count D("scz",1500);
std::thread thra(thread_func, std::ref(A), std::ref(B), 500);
std::thread thrb(thread_func, std::ref(B), std::ref(C), 300);
std::thread thrc(thread_func, std::ref(C), std::ref(A), 500);
std::thread thrd(thread_func, std::ref(D), std::ref(A), 300);
thra.join();
thrb.join();
thrc.join();
thrd.join();
cout << "A: " << A.GetMoney() << endl;
cout << "B: " << B.GetMoney() << endl;
cout << "C: " << C.GetMoney() << endl;
cout << "D: " << D.GetMoney() << endl;
}
std::mutex from;
std::mutex to;
condition_variable cv;
class Count
{
private:
string name;
int money;
public:
Count() :name(), money(0) {}
Count(string n,int m) :name(n),money(m) {}
~Count() {}
string& getName() { return name; }
int GetMoney()const { return money; }
void SetMoney(int m) { money = m; }
};
class Account
{
public:
~Account() = default;
static Account& getInstance()
{
return acc;
}
private:
Account() = default;
Account(const Account&) = delete;
Account& operator=(const Account&) = delete;
std::map<string,Count> s;
static Account acc;
};
Account Account::acc;
void thread_func(Count& A, Count& B, int money)
{
std::unique_lock<std::mutex> lockx(from, std::defer_lock);
std::unique_lock<std::mutex> locky(to, std::defer_lock);
std::lock(lockx, locky);
A.SetMoney(A.GetMoney() - money);
B.SetMoney(B.GetMoney() + money);
}
int main()
{
Count A("zyq",5000);
Count B("cbq",1000);
Count C("hxm",3000);
Count D("scz",1500);
std::thread thra(thread_func, std::ref(A), std::ref(B), 500);
std::thread thrb(thread_func, std::ref(B), std::ref(C), 300);
std::thread thrc(thread_func, std::ref(C), std::ref(A), 500);
std::thread thrd(thread_func, std::ref(D), std::ref(A), 300);
thra.join();
thrb.join();
thrc.join();
thrd.join();
cout << "A: " << A.GetMoney() << endl;
cout << "B: " << B.GetMoney() << endl;
cout << "C: " << C.GetMoney() << endl;
cout << "D: " << D.GetMoney() << endl;
}
|