c++11_多线程_4:condition_variable

  • 引:由上一篇mutex的介绍,基本可知通过设置mutex锁可以解决不同线程修改共享变量的线程安全问题。然而,有些时候并不止要求不同线程间访存的数据安全,而且需要各线程按照某一顺序进行访存或执行(条件变量是并发程序设计中的一种控制结构),这种情况就需要通过设置condition variable(条件变量)实现。条件变量的一般用法是:线程 A 等待某个条件并挂起,直到线程 B 设置了这个条件,并通知条件变量,然后线程 A 被唤醒。经典的 「生产者-消费者」 问题就可以用条件变量来解决。
  • note1:条件变量的等待函数wait(lck) 需要与一个互斥锁搭配使用 ,要明白搭配使用的机理,否则理解上会造成混乱:在调用wait时:
    • 首先该线程需要获取到保护v的锁 进入临界取,因为 v 应该是多个线程可以访问的。
    • 在wait函数执行如下操作:
      • wait函数内部首先 mu.unlock() 释放锁 ;
      • 然后进入等待;
      • 如果被唤醒,则调用mu.lock() 再次获取锁。
  • note2:condition_variable类更多成员函数含义和用法可见.
  • 实例
#include<iostream>
#include<string>
#include<thread>
#include<mutex>
#include<condition_variable>

std::mutex mutex;
std::condition_variable cv;
std::string data;
bool ready = false;//条件
bool processed = false;//条件

void Worker()
{
	std::unique_lock<std::mutex> lock(mutex);
	//等待主线程发送数据
	cv.wait(lock, []() {return ready; });

	// 等待后,继续拥有锁。
	std::cout << "工作线程正在处理数据" << std::endl;

	// 睡眠一秒以模拟数据处理。
	std::this_thread::sleep_for(std::chrono::seconds(1));
	data += "已处理";

	processed = true;
	std::cout << "工作线程通知数据已经处理完毕" << std::endl;

	// 通知前,手动解锁以防正在等待的线程被唤醒后又立即被阻塞。
	lock.unlock();

	cv.notify_one();
}

int main()
{
	std::thread worker(Worker);

	{
		std::lock_guard<std::mutex> lock(mutex);
		std::cout << "主线程正在准备数据..." << std::endl;

		std::this_thread::sleep_for(std::chrono::seconds(1));
		data = "样本数据";
		ready = true;
		std::cout << "主线程通知数据已经准备完毕" << std::endl;
	}
	cv.notify_one();

	{
		std::unique_lock<std::mutex> lock(mutex);
		cv.wait(lock, [] {return processed; });
	}
	std::cout << "回到主线程, 数据 = " << data << std::endl;
	worker.join();

	system("pause");
	return 0;
}
  • 代码说明:
    • 与条件变量搭配使用的「锁」,必须是 unique_lock,不能用 lock_guard(unique_lock锁机制更加灵活,可以再需要的时候进行lock或者unlock调用,而lock_guard不行),通过上边wait函数的原理即可知为什么只能是unique_lock而不能是lock_guard。
    • 条件变量被通知后,挂起的线程就被唤醒,但是唤醒也有可能是假唤醒,或者是因为超时等异常情况,所以被唤醒的线程仍要检查条件是否满足,所以 wait 是放在条件循环里面。cv.wait(lock, [] { return ready; }); 相当于:while (!ready) { cv.wait(lock); }。(condition_variable各成员函数详细
    • 请注意理解main函数中两个大括号{}使用的意义(变量作用域与对象析构)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值