C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++条件标量和互斥锁

C++11中条件标量和互斥锁应用出现死锁问题

作者:hsy12342611

这篇文章主要介绍了C++11中条件标量和互斥锁应用出现死锁思考,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

条件变量和互斥锁在多线程同步过程中经常被使用,以下测试程序测试其使用。

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一样

到此这篇关于C++11中条件标量和互斥锁应用出现死锁思考的文章就介绍到这了,更多相关C++11条件标量和互斥锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文