有的时候仅仅依靠锁住共享资源来使用它是不够的。有时候共享资源只有某些状态的时候才能够使用。比方说,某个线程如果要从堆栈中读取数据,那么如果栈中没有数据就必须等待数据被压栈。这种情况下的同步使用互斥体是不够的。另一种同步的方式--条件变量,就可以使用在这种情况下。条件变量的使用总是和互斥体及共享资源联系在一起的。线程首先锁住互斥体,然后检验共享资源的状态是否处于可使用的状态。如果不是,那么线程就要等待条件变量。要指向这样的操作就必须在等待的时候将互斥体解锁,以便其他线程可以访问共享资源并改变其状态。它还得保证从等到得线程返回时互斥体是被上锁得。当另一个线程改变了共享资源的状态时,它就要通知正在等待条件变量得线程,并将之返回等待的线程。List4是一个使用了boost::condition的简单例子。有一个实现了有界缓存区的类和一个固定大小的先进先出的容器。由于使用了互斥体boost::mutex,这个缓存区是线程安全的。put和get使用条件变量来保证线程等待完成操作所必须的状态。有两个线程被创建,一个在buffer中放入100个整数,另一个将它们从buffer中取出。这个有界的缓存一次只能存放10个整数,所以这两个线程必须周期性的等待另一个线程。为了验证这一点,put和get在std::cout中输出诊断语句。最后,当两个线程结束后,main函数也就执行完毕了。

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <iostream>const int BUF_SIZE = 10;
const int ITERS = 100;boost::mutex io_mutex;class buffer
{public:typedef boost::mutex::scoped_lockscoped_lock;buffer(): p(0), c(0), full(0){}void put(int m){scoped_lock lock(mutex);if (full == BUF_SIZE){{boost::mutex::scoped_locklock(io_mutex);std::cout <<"Buffer is full. Waiting..."<< std::endl;}while (full == BUF_SIZE)cond.wait(lock);}buf[p] = m;p = (p+1) % BUF_SIZE;++full;cond.notify_one();}int get(){scoped_lock lk(mutex);if (full == 0){{boost::mutex::scoped_locklock(io_mutex);std::cout <<"Buffer is empty. Waiting..."<< std::endl;}while (full == 0)cond.wait(lk);}int i = buf[c];c = (c+1) % BUF_SIZE;--full;cond.notify_one();return i;}private:boost::mutex mutex;boost::condition cond;unsigned int p, c, full;int buf[BUF_SIZE];
};buffer buf;void writer()
{for (int n = 0; n < ITERS; ++n){{boost::mutex::scoped_locklock(io_mutex);std::cout << "sending: "<< n << std::endl;}buf.put(n);}
}void reader()
{for (int x = 0; x < ITERS; ++x){int n = buf.get();{boost::mutex::scoped_locklock(io_mutex);std::cout << "received: "<< n << std::endl;}}
}int main(int argc, char* argv[])
{boost::thread thrd1(&reader);boost::thread thrd2(&writer);thrd1.join();thrd2.join();return 0;
}

当需要线程等待某个事物时,可以创建一个condition对象,然后通过这个对象来通知那些等待的线程。

#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#include <list>
#include <string>class Request { /*...*/ };// A simple job queue class; don't do this, use std::queue
template<typename T>
class JobQueue {
public:JobQueue( ) {}~JobQueue( ) {}void submitJob(const T& x) {boost::mutex::scoped_lock lock(mutex_);list_.push_back(x);workToBeDone_.notify_one( );}T getJob( ) {boost::mutex::scoped_lock lock(mutex_);workToBeDone_.wait(lock);// Wait until this condition is// satisfied, then lock the mutexT tmp = list_.front( );list_.pop_front( );return(tmp);}private:std::list<T> list_;boost::mutex mutex_;boost::condition workToBeDone_;
};JobQueue<Request> myJobQueue;void boss( ) {for (;;) {// Get the request from somewhereRequest req;myJobQueue.submitJob(req);}
}void worker( ) {for (;;) {Request r(myJobQueue.getJob( ));// Do something with the job...}
}int main( ) {boost::thread thr1(boss);boost::thread thr2(worker);boost::thread thr3(worker);thr1.join( );thr2.join( );thr3.join( );
}
boost::mutex::scoped_lock lock(mutex_);
workToBeDone_.wait(lock);

这两行代码,第一行锁定这个mutex对象。第二行代码解开这个mutex上的锁,然后进行等待或者休眠,直到它的条件得到了满足。这个mutex互斥对象的解锁让其他的线程能够使用这个mutex对象,它们中的某个需要设置这个等待条件,之后通知另外的线程。

notify_all函数,通知那些所有正在等待某个条件变为真的线程,那些线程随后进入运行状态。wait方法做两件事情:它一直等待直到有人在它正等待的condition上调用notify_one或notify_all,然后它就试图锁定相关的mutex。当调用的是notify_all时,尽管多个等待的线程都尽量去获得下一个锁,但谁将获得依赖于这个mutex的类型和使用的优先策略。

一个condition对象能让消费者线程休眠,因此在还没有碰到一个condition时处理器可以去处理别的事情。例如一个web服务器使用一个工作线程池来处理进来的请求。当没有需求进来时,让这些子线程处于等待状态比让它们循环的查询或者睡眠然后偶尔唤醒来检查这个队列,要好很多。

【Boost】boost库中thread多线程详解10——condition条件变量相关推荐

  1. 【Boost】boost库中thread多线程详解1——thread入门与简介

    1. 概述 线程就是,在同一程序同一时间内允许执行不同函数的离散处理队列. 这使得一个长时间去进行某种特殊运算的函数在执行时不阻碍其他的函数变得十分重要. 线程实际上允许同时执行两种函数,而这两个函数 ...

  2. 【Boost】boost库中thread多线程详解9——thread_specific_ptr线程局部存储

    大多数函数都不是可重入的.这也就是说在某一个线程已经调用了一个函数时,如果你再调用同一个函数,那么这样是不安全的.一个不可重入的函数通过连续的调用来保存静态变量或者是返回一个指向静态数据的指针. 举例 ...

  3. 【Boost】boost库中thread多线程详解5——谈谈线程中断

    线程不是在任意时刻都可以被中断的.如果将线程中函数中的sleep()睡眠等待去掉,那么即使在主线程中调用interrupt()线程也不会被中断.thread库预定义了若干个线程的中断点,只有当线程执行 ...

  4. 【Boost】boost库中thread多线程详解8——call_once仅运行一次

    还有一个问题没有解决:如何使得初始化工作(比如说构造函数)也是线程安全的.比方说,如果一个引用程序要产生唯一的全局的对象,由于实例化顺序的问题,某个函数会被调用来返回一个静态的对象,它必须保证第一次被 ...

  5. 【Boost】boost库中thread多线程详解13——线程标识符

    在boost中也有唯一标识线程的数据结构:thread::id. boost::thread thread_func(func); thread::id var_id = thread_func.ge ...

  6. 【Boost】boost库中thread多线程详解12——线程的分离与非分离

    Boos::thread线程的默认属性为非分离状态,线程结束后线程标识符.线程退出状态等信息需要通过join方法回收. boost::thread thread_func(func); thread_ ...

  7. 【Boost】boost库中thread多线程详解11——线程的休眠和中断

    boost::thread 中提供一个静态方法 void boost::thread::sleep(system_time const& abs_time); 线程将休眠直到时间超时. sle ...

  8. 【Boost】boost库中thread多线程详解6——线程组简单例子

    如果你需要创建几个线程,考虑使用一个线程组对象thread_group来组织它们.一个thread_group对象可以使用多种方法管理线程.首先,可以使用一个指向动态创建的线程对象的指针作为参数来调用 ...

  9. 【Boost】boost库中thread多线程详解2——mutex与lock

    1. mutex对象类 mutex类主要有两种:独占式与共享式的互斥量. ▲ 独占式互斥量: mutex: 独占式的互斥量,是最简单最常用的一种互斥量类型 try_mutex: 它是mutex的同义词 ...

最新文章

  1. Facebook AI新研究:可解释神经元或许会阻碍DNN的学习
  2. MaxCompute助力ofo实现精细化运营:日订单超3200万、整体运行效率提升76%
  3. 建立能够持续请求的CS网络程序
  4. leetcode 592. Fraction Addition and Subtraction | 592. 分数加减运算(最大公因数gcd,最小公倍数lcm)
  5. java 动态队列_RabbitMq之动态修改队列参数
  6. matlab里用fix函数,Matlab基本函数-fix函数
  7. 图形学必备!斯坦福图形学几何处理算法课程2——Shape Matching Correspondence
  8. Eigen编译_Eigen向量化_内存对齐 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  9. python 读取pdf图片_Python如何读取pdf中的图片
  10. 家用NAS有什么用?充分挖掘你的NAS功能
  11. DotaMax网站”获取“自己与职业选手(知名玩家)对战记录
  12. Numpy中矩阵向量乘法np.dot()及np.multiply()以及*区别
  13. Chromium网页Render Layer Tree创建过程分析
  14. oracle笔记二(入门)
  15. 抢红包 作者 陈越单位 浙江大学
  16. 三表子查询IN和distinct的运用
  17. if语句判断真假的几种情况
  18. cisco 华三 对接_h3c开启trunk口与思科设备相互连接
  19. 高德地图开发-常用api踩坑使用
  20. JZ2440挂载nfs

热门文章

  1. 授权码模式-获取令牌
  2. sqoop增量导入hdfs和导出
  3. hystrix服务降级
  4. POI的入门:绘制图形
  5. 解读Redis报错:“MISCONF Redis is configured to save RDB snapshots”
  6. Condition - Java多线程编程
  7. batocera_batocera系统如何把旧电脑改造成影音游戏主机
  8. linux 64位 安装qt creator .run,Qt Creator安装
  9. java main方法调用非静态方法_java中main函数怎么调用外部非static方法
  10. 5.7.22mysql charset_Mysql5.7.22 坑爹的 `character_set_database`