C++11并发与多线程总结(六) --condition_variable条件变量

文章目录

(一) 线程概念、创建及传参
(二) 独占互斥锁–mutex,lock_guardy与其他mutex
(三) unique_lock替换lock_guardy
(四) 单例模式(Singleton)下的线程安全问题
(五) window临界区
(六) condition_variable条件变量
(七) std::async异步任务与std::future< >
(八) packaged_task< >与promise< >
(九) 原子操作atomic<>简介

(1)简介
  1. 通俗的说法就是线程根据条件去拿锁,若不符合条件就休眠
  2. 直到有线程唤醒他,才会继续去竞争锁
  3. 若线程没有进入休眠状态则另一个线程唤醒无效

(2)使用方法

1.std::condition_variable条件变量的wait()函数可堵塞线程
2.调用wait()第一参数是std::unique_lock,第二参数是函数,返回true则返回,否则线程休眠堵塞
3.调用notify_one()唤醒一个线程,若线程没有进入休眠状态则无效
4.notify_all()由于本程序只有一个互斥量 所有效果与one一样
5.若wait中的线程满足了条件则不断进入竞争锁状态,获得锁则继续执行
6. 第二参数传入lambda表达式用于防止虚假唤醒,如多个线程被同时被唤醒后取数据为空
7. 存在问题:被唤醒后若唤醒线程又进入竞争锁状态可能抢不过
8. 竞争锁有可能存在write的数据堆积,写得不好可能稳定

  1. wait() 和 notify()配合使用
	void wait<_Predicate>(std::unique_lock<std::mutex> &__lock, _Predicate __p)
	void wait(std::unique_lock<std::mutex> &__lock)
  • wait()不传入第二参数,相当于互斥锁,条件判定一直返回false,即每次都需要其他线程notify()唤醒,若所有唤醒线程结束运行,没有线程唤醒他则堵塞卡死
	condition_variable m_codition; //条件变量
	std::unique_lock<mutex> myulock(m_mutex);  //使用前不能lock
	m_codition.wait(myulock);
  • 另一个线程
	m_codition.notify_one();  //唤醒线程

  1. wait()传入俩参数,第一个为unique_lock,第二参数为lambda表达式或其他函数,返回值必须为布尔值

  • 被唤醒后ambda函数若返回ture则进入竞争锁状态,抢不到则继续判断,抢到则继续执行,被唤醒后lambda函数返回false则继续休眠
	std::unique_lock<mutex> myulock(m_mutex1);  //使用前不能lock

	auto lambda = [this]
	{
		//判断条件
		return true;
	};
	m_codition.wait(myulock, lambda);
	//...
	//操作共享数据
	//...
	myulock.unlock();//提前解锁提高效率
  1. notify_all()即唤醒所有在wait()中的线程,进入竞争锁状态,由于本程序只有一个互斥量 所有效果与one一样

  • 测试代码段
#include <iostream>
#include<thread>
#include<mutex>
#include<list>

using namespace std;

class CReadAndWrite
{
public:
	CReadAndWrite() {};
	void read();
	void wirte();

private:
	list<int> m_list;
	mutex m_mutex1;
	mutex m_mutex2;
	condition_variable m_codition; //条件变量
};

void CReadAndWrite::wirte()
{
	for (int i = 0; i < 100; i++)
	{
		std::unique_lock<mutex> myulock(m_mutex1);

		m_list.push_back(i);		

		myulock.unlock();
		m_codition.notify_one();  //唤醒线程

		cout << "write  " << i << endl;
	}
}

void CReadAndWrite::read()
{
	for (int i = 0; i < 100; i++)
	{

			std::unique_lock<mutex> myulock(m_mutex1);  //使用前不能lock

			auto lambda = [this]
			{
				//cout << "空~~~" << endl;
				return !m_list.empty();
			};
			m_codition.wait(myulock, lambda);
			int num = m_list.front();
			
			m_list.pop_front();
			myulock.unlock();//提前解锁提高效率

			cout << "输出 num = " << num << endl;
	}
}



int main()
{


	CReadAndWrite obj;
	thread mywrite(&CReadAndWrite::wirte, &obj);
	thread myread(&CReadAndWrite::read, &obj);

	mywrite.join();
	myread.join();

	std::cout << "Main end!\n";
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值