C++11 并发与多线程(八、condition_variable,wait,notify_one,notify_all)

一、条件变量 condition_variable wait notify_one

1.condition_variable

  1. condition_variable :实际上是一个类,等待一个条件达成,需要和互斥量来配合,用的时候我们要生成这个类的对象

2.wait()函数

条件变量类对象的成员函数,用来等一个东西 ;

  • 如果第二个参数的lambda表达式返回 true , 那么wait()最接返回;
  • 如果第二个参数的lambda表达式返回 false ,那么wait()将解锁互斥量,并阻塞到本行;阻塞到其他某个线程调用notify_one()成员函数为止;
  • 如果wait()没有第二个参数 varible.wait(unique) ;那么就和第二个参数lambda表达式返回false效果一样;
  • 当其他线程用notify_one()将本wait(原来是阻塞)的状态唤醒后,wait()会不断的尝试重新获取互斥量锁 ;如果获取不到,那么就会卡在wait()这里等着,如果获取到了,wait()就继续执行上锁;
  • 如果wait()有第二个参数lambda表达式,如果表达式为false 那么wait()将解锁互斥量,并阻塞到本行;如果为 true 则返回,流程就继续走下去(此时互斥锁被锁着);
  • 如果wait没有第二个参数 ,则wait()返回,流程将继续走下去
while (true)
		{
			unique_lock<std::mutex> unique(mutex1);
			//wait() 条件变量类对象的成员函数,用来等一个东西
			//如果第二个参数的lambda表达式返回 true , 那么wait()最接返回
			//如果第二个参数的lambda表达式返回 false ,那么wait()将解锁互斥量,并阻塞到本行
			//阻塞到其他某个线程调用notify_one()成员函数为止
			//如果wait()没有第二个参数 varible.wait(unique) ;那么就和第二个参数lambda表达式返回false效果一样
			//当其他线程用notify_one()将本wait(原来是阻塞)的状态唤醒后,wait()会不断的尝试重新获取互斥量锁 
			//如果获取不到,那么就会卡在wait()这里等着,如果获取到了,wait()就继续执行上锁,如果wait()有第二个参数lambda表达式,如果表达式为
			// false 那么wait()将解锁互斥量,并阻塞到本行
			// 如果为 true 则返回,流程就继续走下去(此时互斥锁被锁着)
			// 如果wait没有第二个参数 ,则wait()返回,流程将继续走下去
			varible.wait(unique, [this]() {	//一个lambda就是一个可调用对象
				if (!m_list.empty())
				{
					return true;
				}
				return false;
			});
			nCommand = m_list.front();	//返回第一个元素,但不检查元素是否存在 所以要判断是否为空
			m_list.pop_front();		//移除第一个元素,但不返回
			unique.unlock();	//因为unique_lock的灵活性,我们可以随时unlock解锁,以免锁太长时间

			cout << "移除一个元素 : " << nCommand << endl;
		}

完整代码演示:

class Test
{
public:
	Test() {};
	~Test() {};

	//把收到的消息(玩家命令)入到一个队列的线程
	void InQueue()
	{
		for (int i = 0; i < 100000; ++i)
		{
			cout << "插入一个元素 : " << i << endl;

			std::lock_guard<std::mutex> guard1(mutex1);

			m_list.push_back(i);
			varible.notify_one();		//我们尝试把wait()的线程唤醒 执行完这行 那么OutQueue()里面的wait()就会被唤醒
		}
	}
	//出队列线程函数
	void OutQueue()
	{
		int nCommand = 0;
		while (true)
		{
			unique_lock<std::mutex> unique(mutex1);
			varible.wait(unique, [this]() {	//一个lambda就是一个可调用对象
				if (!m_list.empty())
				{
					return true;
				}
				return false;
			});
			nCommand = m_list.front();	//返回第一个元素,但不检查元素是否存在 所以要判断是否为空
			m_list.pop_front();		//移除第一个元素,但不返回
			unique.unlock();	//因为unique_lock的灵活性,我们可以随时unlock解锁,以免锁太长时间

			cout << "移除一个元素 : " << nCommand << endl;
		}
	}

private:
	list<int> m_list;	//容器(消息队列),专门用于代表玩家发过来的命令
	mutex mutex1;
	condition_variable varible;	//条件变量对象
};

int main()
{
	Test test;
	thread obj1(&Test::InQueue, &test);
	thread obj2(&Test::OutQueue, &test);
	obj1.join();
	obj2.join();

	cout << "I Love China" << endl;

    return 0;
}

3. notify_one() 只能通知一个线程

4. notify_all() 通知多个线程(适用于多个线程在wait()下)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值