条件变量和互斥锁在多线程同步过程中经常被使用,以下测试程序测试其使用。
目录
1.测试程序1
2.测试程序2
3.运行结果思考
1.测试程序1
#include <mutex>
#include <deque>
#include <iostream>
#include <thread>
#include <condition_variable>class MCTest {
public:MCTest() : m_work(true), m_max_num(30), m_next_index(0) {}void producer_thread() {while (m_work) {std::this_thread::sleep_for(std::chrono::milliseconds(500));std::unique_lock<std::mutex> lk(m_cvMutex);m_cv.wait(lk);m_data.push_back(m_next_index++);std::cout << "producer " << m_next_index << ", queue size: " << m_data.size() << std::endl;m_cv.notify_all();}}void consumer_thread() {while (m_work) {std::unique_lock<std::mutex> lk(m_cvMutex);m_cv.wait(lk);int data = m_data.front();m_data.pop_front();std::cout << "consumer " << data << ", deque size: " << m_data.size() << std::endl;m_cv.notify_all();}}
private:bool m_work;std::mutex m_cvMutex;std::condition_variable m_cv;std::deque<int> m_data;size_t m_max_num;int m_next_index;
};int main() {MCTest obj;std::thread tp = std::thread(&MCTest::producer_thread, &obj);std::thread tc = std::thread(&MCTest::consumer_thread, &obj);tp.join();tc.join();return 0;
}
运行结果:
2.测试程序2
#include <mutex>
#include <deque>
#include <iostream>
#include <thread>
#include <condition_variable>class MCTest {
public:MCTest() : m_work(true), m_max_num(30), m_next_index(0) {}void producer_thread() {while (m_work) {std::this_thread::sleep_for(std::chrono::milliseconds(500));std::unique_lock<std::mutex> lk(m_cvMutex);m_cv.wait(lk, [this]() -> bool { return this->m_data.size() < this->m_max_num; });m_data.push_back(m_next_index++);std::cout << "producer " << m_next_index << ", queue size: " << m_data.size() << std::endl;m_cv.notify_all();}}void consumer_thread() {while (m_work) {std::unique_lock<std::mutex> lk(m_cvMutex);m_cv.wait(lk, [this] { return !this->m_data.empty(); });int data = m_data.front();m_data.pop_front();std::cout << "consumer " << data << ", deque size: " << m_data.size() << std::endl;m_cv.notify_all();}}
private:bool m_work;std::mutex m_cvMutex;std::condition_variable m_cv;std::deque<int> m_data;size_t m_max_num;int m_next_index;
};int main() {MCTest obj;std::thread tp = std::thread(&MCTest::producer_thread, &obj);std::thread tc = std::thread(&MCTest::consumer_thread, &obj);tp.join();tc.join();return 0;
}
运行结果:
3.运行结果思考
为什么测试1程序没有任何输出,出现死锁,而程序2正常交替执行?
程序1条件变量在得到通知之前会一直wait,如果线程1获取了锁后,阻塞于wait调用,释放了互斥锁,等待通知。此时线程2执行,线程2获取锁后,阻塞于阻塞于wait调用,并释放互斥锁,等待唤醒。本质上是处于死锁状态。
程序2条件变量处于wait阻塞时,除了得到通知会解除阻塞外,第二个参数为true时,wait函数也会返回,所以避免了死锁的存在。
总结一下,wait函数参数2含义如下:
(1)如果参数为true,即使没有收到通知,wait也会返回,此时本线程互斥量已经加锁
(2)如果参数为false,在没有收到通知时,解锁互斥量wait一直阻塞
(3)如果没有参数,与false一样