網(wǎng)站首頁 編程語言 正文
前言
有這樣的需求
一個線程需要等待另一個線程執(zhí)行完畢之后它才會繼續(xù)向下執(zhí)行,這該如何實現(xiàn)? condition_variable類中實現(xiàn)了wait方法
wait()
- 可以接受兩個參數(shù),其中第一個參數(shù)是鎖對象,第二個參數(shù)是lambda表達式,其中的lambda表達式的返回值要是bool類型
- 也可接受一個參數(shù),僅僅接受鎖對象
#include<iostream>
#include<mutex>
#include<list>
#include<thread>
using namespace std;
class Obj
{
private:
list<int> myList;
condition_variable var;
mutex tex;
public:
bool popFromList(int & comb)
{
if (!myList.empty()) {
unique_lock<mutex> cur(tex);
if (!myList.empty())
{
comb = myList.front();
myList.pop_front();
return true;
}
}
return false;
}
void inToList()
{
for (int i = 0; i < 100; i++)
{
unique_lock<mutex> cur(tex);
myList.push_back(i);
cout << this_thread::get_id() << "正在向list中添加數(shù)據(jù)>; " << i << endl;
var.notify_one();
}
}
void outFromList()
{
while(true)
{
unique_lock<mutex> cur(tex);
var.wait(cur, [this] {
if (!myList.empty())
return true;
return false;
});
int comb = myList.front();
myList.pop_front();
cout << this_thread::get_id() << "正在取出數(shù)據(jù)>: " << comb << endl;
}
}
};
int main()
{
Obj obj;
thread thread1(&Obj::outFromList, &obj);
thread thread2(&Obj::inToList, &obj);
thread1.join();
thread2.join();
cout << "這里是主線程" << endl;
}
線程1執(zhí)行到wait函數(shù)時,會執(zhí)行l(wèi)ambda表達式
返回值為false時,這個線程就會將鎖打開,將該線程壓入到棧中,執(zhí)行下一個線程 下一個線程執(zhí)行完畢之后執(zhí)行notify_one后就會返回到該線程,繼續(xù)執(zhí)行l(wèi)ambda表達式
返回值為true時就嘗試獲得鎖
獲得鎖后繼續(xù)執(zhí)行下面的語句
沒有獲得鎖就繼續(xù)卡在wait等待獲取到鎖
返回值為false時,繼續(xù)將鎖打開,線程壓入棧,執(zhí)行下一個線程
返回值為true時,線程繼續(xù)執(zhí)行
運行結(jié)果可能是一個線程執(zhí)行完畢另一個線程再執(zhí)行
這不就是順序執(zhí)行嗎?
其實并不是這樣的
notify_one()
喚醒wait()函數(shù),當(dāng)前所再的線程嘗試獲得鎖
某個線程執(zhí)行完notify_one函數(shù)后,會返回到另一個線程中的wait函數(shù)處,并將其"喚醒",讓其繼續(xù)執(zhí)行,自己的線程和wait線程都嘗試獲得鎖來進行下一步執(zhí)行
不是順序執(zhí)行的解釋
- 當(dāng)wait函數(shù)后面有很多語句要執(zhí)行,但是再此之前wait所在的線程函數(shù)中就已經(jīng)將鎖進行釋放了,那么notify_one的“喚醒”就不在生效,兩個線程都嘗試獲得鎖,但是wait所在的線程有很多語句要執(zhí)行,耗時高,那么很有可能notify_one所在的線程就再次獲得了鎖,進行下一步操作。
- 這樣就不一定是順序執(zhí)行的宏觀表現(xiàn)了
#include<iostream>
#include<mutex>
#include<list>
#include<thread>
using namespace std;
class Obj
{
private:
list<int> myList;
condition_variable var;
mutex tex;
public:
bool popFromList(int & comb)
{
if (!myList.empty()) {
unique_lock<mutex> cur(tex);
if (!myList.empty())
{
comb = myList.front();
myList.pop_front();
return true;
}
}
return false;
}
void inToList()
{
for (int i = 0; i < 1000; i++)
{
cout << this_thread::get_id() << "正在向list中添加數(shù)據(jù)>; " << i << endl;
unique_lock<mutex> cur(tex);
myList.push_back(i);
var.notify_one();
}
}
void outFromList()
{
while(true)
{
unique_lock<mutex> cur(tex);
var.wait(cur, [this] {
if (!myList.empty())
return true;
return false;
});
int comb = myList.front();
myList.pop_front();
cur.unlock();
cout << this_thread::get_id() << "正在取出數(shù)據(jù)>: " << comb << endl;
chrono::seconds tim(2);
this_thread::sleep_for(tim);
cout <<this_thread::get_id() << "睡眠兩秒后執(zhí)行" << endl;
}
}
};
int main()
{
Obj obj;
thread thread1(&Obj::outFromList, &obj);
thread thread2(&Obj::inToList, &obj);
thread1.join();
thread2.join();
cout << "這里是主線程" << endl;
}
如圖所示,在notify_one線程執(zhí)行835次循環(huán)后,wait所在的線程才獲得了鎖,繼續(xù)執(zhí)行
在此之前的所有notify_one的喚醒操作都是無效的。
然后在notify_one線程執(zhí)行完畢之后,wait再次獲得了鎖,繼續(xù)向下執(zhí)行
notify_all()
顧名思義,是“喚醒”所有的wait函數(shù)線程,但是并不是都一起運行,因為他們要進行鎖的請求,僅僅只能由一把鎖存在,只有獲得鎖并且lambda表達式返回結(jié)果為true的線程才能繼續(xù)執(zhí)行
原文鏈接:https://blog.csdn.net/m0_56104219/article/details/126911671
相關(guān)推薦
- 2022-03-17 C#表達式樹Expression動態(tài)創(chuàng)建表達式_C#教程
- 2022-05-05 Android開發(fā)使用WebView打造web?app示例代碼_Android
- 2022-12-24 React重新渲染超詳細講解_React
- 2022-08-06 winform把Office轉(zhuǎn)成PDF文件_C#教程
- 2022-02-23 Proxy error Could not proxy request錯誤解決
- 2022-06-28 ASP.NET?WebAPI導(dǎo)入CSV_實用技巧
- 2021-12-02 利用Matlab仿真實現(xiàn)圖像煙霧識別(k-means聚類圖像分割+LBP+PCA+SVM)_C 語言
- 2022-10-19 Pandas如何將表格的前幾行生成html實戰(zhàn)案例_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支