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)級(jí)的線程調(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++數(shù)據(jù)結(jié)構(gòu)與算法之反轉(zhuǎn)鏈表的方法詳解
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)與算法之反轉(zhuǎn)鏈表的方法,結(jié)合實(shí)例形式分析了C++反轉(zhuǎn)鏈表的原理、實(shí)現(xiàn)方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-08-08
vc中float與DWORD的互想轉(zhuǎn)換實(shí)現(xiàn)代碼
這篇文章主要介紹了vc中float與DWORD的互想轉(zhuǎn)換實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-06-06
C++如何解決rand()函數(shù)生成的隨機(jī)數(shù)每次都一樣的問題
這篇文章主要介紹了C++如何解決rand()函數(shù)生成的隨機(jī)數(shù)每次都一樣的問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08

