多執行緒程式
競態條件:多執行緒程式執行的結果是一致的,不會隨著CPU對執行緒不同的呼叫順序而產生不同的運行結果.

解決?:互斥鎖 mutex
經典的賣票問題,三個執行緒賣100張票
代碼1
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
int ticketCount = 100;
std::mutex mtx;//互斥鎖
void sellTicket(int window) {
while (ticketCount > 0) {
mtx.lock();
std::cout << "視窗" << window << "銷售" << ticketCount << std::endl;
ticketCount--;
mtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}//end
int main() {
std::list<std::thread> tlist;
for (int i = 0; i < 3; i++) {
tlist.push_back(std::thread(sellTicket,i));
}
for (std::thread & t : tlist) {
t.join();
}
system("pause");
return 0;
}
上面代碼的問題...
while (ticketCount > 0) {
mtx.lock();
std::cout << "視窗" << window << "銷售" << ticketCount << std::endl;
ticketCount--;
mtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
如果ticketCount =1 ,當前有一個執行緒A while (ticketCount > 0)為true,執行緒A還沒執行ticketCount--完成時,cpu交給了執行緒B
執行緒B while (ticketCount > 0)也為true,進入 回圈體內,造成了買0號票,改進如下
代碼2
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
int ticketCount = 100;
std::mutex mtx;//互斥鎖
void sellTicket(int window) {
while (ticketCount > 0) {
mtx.lock();
if(ticketCount >0){
std::cout << "視窗" << window << "銷售" << ticketCount << std::endl;
ticketCount--;
}
mtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}//end
int main() {
std::list<std::thread> tlist;
for (int i = 0; i < 3; i++) {
tlist.push_back(std::thread(sellTicket,i));
}
for (std::thread & t : tlist) {
t.join();
}
system("pause");
return 0;
}
代碼2還有些問題!! 如下
mtx.lock();
代碼
代碼
代碼
代碼
.....
mtx.unlock();
如果在代碼lock()和unlock()之間 非常回傳,導致mtx沒有正常unlock(),那么出現死鎖問題 =》智能指標 lock_gurad unique_lock
看lock_gurad

#include <iostream>
#include <thread>
#include <list>
#include <mutex>
int ticketCount = 100;
std::mutex mtx;//互斥鎖
void sellTicket(int window) {
while (ticketCount > 0) {
{
std::lock_guard<std::mutex> lock(mtx);
std::cout << "視窗" << window << "銷售" << ticketCount << std::endl;
ticketCount--;
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
}//end
int main() {
std::list<std::thread> tlist;
for (int i = 0; i < 3; i++) {
tlist.push_back(std::thread(sellTicket,i));
}
for (std::thread & t : tlist) {
t.join();
}
system("pause");
return 0;
}

上面的圖片中我們知道lock_gurad 的拷貝建構式被關閉了,所以當我們遇到函式呼叫需要拷貝構造lock_guard的時候,就有障礙了,這個時候可以用unique_lock
unique_lock 轉移指標,支持帶右值得拷貝賦值,支持引數傳遞拷貝構造的,他的左值的拷貝構造也是被關閉了 看下圖

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539759.html
標籤:其他
下一篇:Python工具箱系列(十九)
