C++中std::condition_variable 條件變量的使用
作用:std::condition_variable 是 C++ 多線程編程中用于線程間同步的核心工具,其使用場景和核心價(jià)值體現(xiàn)在以下幾個(gè)方面:
一、何時(shí)使用 std::condition_variable?
?線程需要等待特定條件成立當(dāng)某個(gè)線程必須等待共享資源的某個(gè)狀態(tài)(如隊(duì)列非空、任務(wù)完成、數(shù)據(jù)就緒等)時(shí),使用條件變量可以避免忙等待(busy-waiting),從而減少 CPU 資源的浪費(fèi)。
?經(jīng)典場景:- ?生產(chǎn)者-消費(fèi)者模型:消費(fèi)者線程等待隊(duì)列中有數(shù)據(jù)時(shí),生產(chǎn)者線程在添加數(shù)據(jù)后通過
notify_one()或notify_all()通知消費(fèi)者。 - ?任務(wù)調(diào)度:工作線程等待任務(wù)隊(duì)列中出現(xiàn)新任務(wù)。
- ?生產(chǎn)者-消費(fèi)者模型:消費(fèi)者線程等待隊(duì)列中有數(shù)據(jù)時(shí),生產(chǎn)者線程在添加數(shù)據(jù)后通過
?需要多線程協(xié)作完成復(fù)雜邏輯當(dāng)多個(gè)線程需要按特定順序協(xié)作時(shí)(如線程 A 完成預(yù)處理后通知線程 B 執(zhí)行),條件變量提供了一種高效的協(xié)調(diào)機(jī)制。
?示例:主線程等待所有子線程初始化完成后再啟動(dòng)核心邏輯。?避免輪詢和資源浪費(fèi)若用
while (條件不滿足) { sleep(); }實(shí)現(xiàn)等待,會(huì)導(dǎo)致線程頻繁切換上下文和無效輪詢,而條件變量通過阻塞線程直接釋放 CPU,直到被主動(dòng)喚醒。?需要?jiǎng)討B(tài)調(diào)整線程行為例如,線程池中的工作線程根據(jù)任務(wù)負(fù)載動(dòng)態(tài)休眠或喚醒。
?二、為什么使用 std::condition_variable?
?解決線程同步中的“等待-通知”問題條件變量通過 wait() 和 notify_*() 的組合,實(shí)現(xiàn)線程間的精準(zhǔn)通知機(jī)制:
- wait():釋放互斥鎖并阻塞線程,允許其他線程操作共享資源。
- ?notify_one()/notify_all():喚醒一個(gè)或所有等待線程,確保資源狀態(tài)變化后及時(shí)響應(yīng)。
?避免虛假喚醒(Spurious Wakeup)?操作系統(tǒng)的底層實(shí)現(xiàn)可能導(dǎo)致線程被意外喚醒(即使未收到通知)。條件變量通過 ?謂詞(Predicate)? 參數(shù)(如 cv.wait(lock, []{ return ready; }))確保只有在條件真正滿足時(shí)才繼續(xù)執(zhí)行。
?優(yōu)化鎖的粒度條件變量與 std::mutex 配合使用時(shí),允許在等待期間釋放鎖,其他線程可繼續(xù)操作共享資源,避免長時(shí)間鎖競爭。
?替代低效的輪詢機(jī)制相比輪詢(如 sleep() + 循環(huán)檢查),條件變量通過操作系統(tǒng)級的線程調(diào)度實(shí)現(xiàn)高效阻塞,減少 CPU 占用。
?三、使用示例與核心步驟
?基本流程
?定義共享變量和同步工具:
std::mutex mtx; std::condition_variable cv; bool data_ready = false;
?等待線程:
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return data_ready; }); // 阻塞直到 data_ready 為 true?通知線程:
{
std::lock_guard<std::mutex> lock(mtx);
data_ready = true;
}
cv.notify_one(); // 喚醒一個(gè)等待線程?經(jīng)典案例:生產(chǎn)者-消費(fèi)者模型
#include <queue>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> task_queue;
void producer() {
for (int i = 0; i < 10; ++i) {
{
std::lock_guard<std::mutex> lock(mtx);
task_queue.push(i);
}
cv.notify_one(); // 通知消費(fèi)者
}
}
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !task_queue.empty(); }); // 等待隊(duì)列非空
int task = task_queue.front();
task_queue.pop();
lock.unlock();
// 處理任務(wù)
}
}?四、注意事項(xiàng)
?必須與互斥鎖配合使用:
所有對共享變量的修改和訪問必須通過互斥鎖保護(hù),否則會(huì)導(dǎo)致競態(tài)條件(Race Condition)。?正確處理虛假喚醒:
始終使用帶謂詞的wait()形式(如cv.wait(lock, predicate))。?避免“喚醒丟失”?:
確保在修改共享狀態(tài)后調(diào)用notify_*(),否則等待線程可能永遠(yuǎn)阻塞。
?總結(jié)
std::condition_variable 的核心價(jià)值在于通過 ?等待-通知機(jī)制 實(shí)現(xiàn)高效的線程同步,適用于需要協(xié)調(diào)多個(gè)線程行為、避免資源浪費(fèi)的場景。其設(shè)計(jì)解決了傳統(tǒng)輪詢的低效問題,并通過與互斥鎖的配合優(yōu)化了多線程程序的性能與安全性。
到此這篇關(guān)于C++中std::condition_variable 條件變量的使用的文章就介紹到這了,更多相關(guān)C++ std::condition_variable 條件變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)詳解
大家好,本篇文章主要講的是C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01
C語言main函數(shù)的參數(shù)及其返回值詳細(xì)解析
main函數(shù)的返回值用于說明程序的退出狀態(tài)。如果返回0,則代表程序正常退出;返回其它數(shù)字的含義則由系統(tǒng)決定。通常,返回非零代表程序異常退出2013-10-10
C++避免棧內(nèi)存溢出的幾種實(shí)現(xiàn)方法
在C++編程中,一個(gè)線程的棧內(nèi)存通常是有限的,本文就來詳細(xì)介紹幾種避免棧溢出的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-09-09
C++實(shí)現(xiàn)二叉樹的堂兄弟節(jié)點(diǎn)查詢
C++實(shí)現(xiàn)二叉樹的堂兄弟節(jié)點(diǎn)查詢,是指在二叉樹中,找到兩個(gè)節(jié)點(diǎn)深度相同但父節(jié)點(diǎn)不同的節(jié)點(diǎn),即為堂兄弟節(jié)點(diǎn)。實(shí)現(xiàn)這一功能可以通過遍歷二叉樹并記錄節(jié)點(diǎn)深度和父節(jié)點(diǎn)來實(shí)現(xiàn)2023-04-04
C++ OpenCV實(shí)戰(zhàn)之手寫數(shù)字識別
這篇文章主要為大家詳細(xì)介紹了如何使用machine learning機(jī)器學(xué)習(xí)模塊進(jìn)行手寫數(shù)字識別功能,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-08-08

