C++11中的condition_variable
在C++11中,條件變量(std::condition_variable
)是線程同步機制之一,用于在多線程環境中實現線程間的通信和協調。它允許一個或多個線程在某個條件尚未滿足時等待,直到其他線程通知條件已經滿足。條件變量通常與互斥鎖(std::mutex
)一起使用,以確保線程安全。
1. 包含頭文件
在使用條件變量之前,需要包含 <condition_variable>
和 <mutex>
頭文件:
#include <condition_variable>
#include <mutex>
2. 聲明條件變量和互斥鎖
條件變量需要與互斥鎖配合使用,互斥鎖用于保護共享資源,條件變量用于線程間的同步。
std::mutex mtx; // 互斥鎖
std::condition_variable cv; // 條件變量
3. 等待條件
線程可以通過 cv.wait()
或 cv.wait_for()
等方法等待條件滿足。cv.wait()
需要一個互斥鎖作為參數,并且會自動釋放互斥鎖,直到條件變量被通知為止。在等待期間,線程會被阻塞。
std::unique_lock<std::mutex> lock(mtx); // 加鎖
cv.wait(lock,[](){return condition; };);// 等待條件滿足
condition
是一個布爾表達式,用于判斷是否滿足等待條件。std::unique_lock
是一種更靈活的互斥鎖,支持延遲加鎖和解鎖。
4. 通知條件
當條件滿足時,可以通過 cv.notify_one()
或 cv.notify_all()
喚醒等待的線程:
cv.notify_one()
:喚醒一個等待的線程。cv.notify_all()
:喚醒所有等待的線程。
示例代碼
以下是一個完整的示例,展示了如何使用條件變量實現生產者-消費者模型:
#include <iostream>
#include<mutex>
#include<condition_variable>
#include<thread>
#include<queue>
using namespace std;std::queue<int> que; // 共享隊列
std::mutex mtx; // 互斥鎖
std::condition_variable cv; // 條件變量// 生產者線程
void Producer()
{for (int i = 0; i < 10; i++){std::unique_lock<std::mutex> lock(mtx); // 加鎖que.push(i); // 生產數據cout << "Producer " << i << endl;lock.unlock();cv.notify_one(); // 通知消費者std:this_thread::sleep_for(std::chrono::milliseconds(100));}
}// 消費者線程
void Customer()
{while (true){std::unique_lock<std::mutex> lock(mtx); // 加鎖cv.wait(lock, []() {return !que.empty(); }); // 等待隊列非空int nValue = que.front(); // 消費數據que.pop();std::cout << "customer " << nValue << endl;if (nValue == 9)break;lock.unlock();std:this_thread::sleep_for(std::chrono::milliseconds(100));}
}int main()
{std::thread th1(Producer);std::thread th2(Customer);th1.join();th2.join();std::cout << "Hello World!\n";
}
代碼運行結果:
注意事項
- 條件變量必須與互斥鎖配合使用,否則會導致未定義行為。
- 虛假喚醒:
cv.wait()
可能會因為虛假喚醒而被觸發,因此需要在等待條件中使用循環或條件表達式來確保條件真正滿足。 - 線程安全:在使用條件變量時,必須確保共享資源的訪問是線程安全的,通常通過互斥鎖來保護共享資源。
通過合理使用條件變量,可以實現高效的線程同步和通信,適用于生產者-消費者、線程池等多種場景。
說明:以上代碼來自kimi AI助手。