多線程程式 競態條件:多線程程式執行的結果是一致的,不會隨著CPU對線程不同的調用順序而產生不同的運行結果. 解決?:互斥鎖 mutex 經典的賣票問題,三個線程賣100張票 代碼1 #include <iostream> #include <thread> #include <list> #inc ...
多線程程式
競態條件:多線程程式執行的結果是一致的,不會隨著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 轉移指針,支持帶右值得拷貝賦值,支持參數傳遞拷貝構造的,他的左值的拷貝構造也是被關閉了 看下圖