C++ boost thread学习(二)

条件变量

如果线程之间执行顺序上有依赖关系,可使用条件变量(Condition variables)。

可以到boost官网中参考条件变量(Condition variables)的使用。

条件变量必须和互斥量配合使用,等待另一个线程重某个事件的发生(满足某个条件),然后线程才能继续执行。

共有两种条件变量对象condition_variable, condition_variable_any,一般情况下使用condition_variable_any。

条件变量的使用方式: 
拥有条件变量的线程先锁定互斥量,然后循环检查某个条件,如果条件不满足,那么就调用条件变量的成员函数wait()等待直到条件满足。其他线程处理条件变量要求的条件,当条件满足时调用它的成员函数notify_one()或者notify_all(),以通知一个或者所有正在等待条件的变量的线程停止等待继续执行。

例子:生产--消费模型。

缓冲区buffer使用了两个条件变量cond_put和cond_get,分别用于处理put动作和get动作,如果缓冲区满则cond_put持续等待,当cond_put得到通知 (缓冲区不满)时线程写入数据,然后通知cond_get条件变量可以获取数据。cond_get的处理流程与cond_put类似。

C++代码  

  1. #include <boost/thread.hpp>
  2. #include <boost/thread/mutex.hpp>
  3. #include <iostream>
  4. #include <stack>
  5. using namespace std;
  6. boost::mutex io_mu;
  7. class buffer
  8. {
  9. private:
  10. boost::mutex mu; // 互斥量,配合条件变量使用
  11. boost::condition_variable_any cond_put; // 写入条件变量
  12. boost::condition_variable_any cond_get; // 读取条件变量
  13. stack<int> stk; // 缓冲区对象
  14. int un_read, capacity;
  15. bool is_full() // 缓冲区满判断
  16. {
  17. return un_read == capacity;
  18. }
  19. bool is_empty()  // 缓冲区空判断
  20. {
  21. return un_read == 0;
  22. }
  23. public:
  24. buffer(size_t n) : un_read(0), capacity(n){}  // 构造函数
  25. void put(int x)  // 写入数据
  26. {
  27. { // 开始一个局部域
  28. boost::mutex::scoped_lock lock(mu); //锁定互斥量
  29. while ( is_full() ) // 检查缓冲区是否满
  30. {
  31. { // 局部域,锁定cout输出一条信息
  32. boost::mutex::scoped_lock lock(io_mu);
  33. cout << "full waiting..." << endl;
  34. }
  35. cond_put.wait(mu); // 条件变量等待
  36. } // 条件变脸满足,停止等待
  37. stk.push(x); // 压栈,写入数据
  38. ++un_read;
  39. } // 解锁互斥量,条件变量的通知不需要互斥量锁定
  40. cond_get.notify_one(); // 通知可以读取数据
  41. }
  42. void get(int *x) // 读取数据
  43. {
  44. { // 局部域开始
  45. boost::mutex::scoped_lock lock(mu); // 锁定互斥量
  46. while (is_empty()) // 检查缓冲区是否空
  47. {
  48. {
  49. boost::mutex::scoped_lock lock(io_mu);
  50. cout << "empty waiting..." << endl;
  51. }
  52. cond_get.wait(mu); // 条件变量等待
  53. }
  54. --un_read;
  55. *x = stk.top(); // 读取数据
  56. stk.pop(); // 弹栈
  57. }
  58. cond_put.notify_one(); // 通知可以写入数据
  59. }
  60. };
  61. buffer buf(5); // 一个缓冲区对象
  62. void producter(int n) // 生产者
  63. {
  64. for (int i = 0; i < n; ++i)
  65. {
  66. {
  67. boost::mutex::scoped_lock lock(io_mu);
  68. cout << "put " << i << endl;
  69. }
  70. buf.put(i); // 写入数据
  71. }
  72. }
  73. void consumer(int n) // 消费者
  74. {
  75. int x;
  76. for (int i = 0; i < n; ++i)
  77. {
  78. buf.get(&x); // 读取数据
  79. boost::mutex::scoped_lock lock(io_mu);
  80. cout << "get " << x << endl;
  81. }
  82. }
  83. int main()
  84. {
  85. boost::thread t1(producter, 20); // 一个生产者线程
  86. boost::thread t2(consumer, 10); // 两个消费者线程
  87. boost::thread t3(consumer, 10);
  88. t1.join();
  89. t2.join();
  90. t3.join();
  91. return 0;
  92. }

运行结果: 
empty waiting... 
put 0 
empty waiting... 
put 1 
put 2 
get 1 
get 2 
get 0 
empty waiting... 
empty waiting... 
put 3 
put 4 
put 5 
put 6 
put 7 
get 6 
get 7 
get 5 
get 4 
get 3 
empty waiting... 
put 8 
empty waiting... 
put 9 
put 10 
put 11 
get 9 
get 11 
get 8 
empty waiting... 
put 12 
put 13 
put 14 
put 15 
put 16 
put 17 
full waiting... 
get 10 
get 16 
put 18 
full waiting... 
get 17 
get 15 
get 14 
get 13 
get 12 
get 18 
empty waiting... 
put 19 
get 19

时间: 2024-10-24 22:43:29

C++ boost thread学习(二)的相关文章

Boost Thread学习笔记二

除了thread,boost::thread另一个重要组成部分是mutex,以及工作在mutex上的boost::mutex::scoped_lock.condition和barrier,这些都是为实现线程同步提供的. mutexboost提供的mutex有6种:boost::mutexboost::try_mutexboost::timed_mutexboost::recursive_mutexboost::recursive_try_mutexboost::recursive_timed_m

Boost Thread学习笔记

thread自然是boost::thread库的主 角,但thread类的实现总体上是比较简单的,前面已经说过,thread只是一个跨平台的线程封装库,其中按照所使用的编译选项的不同,分别决定使用 Windows线程API还是pthread,或者Macintosh Carbon平台的thread实现.以下只讨论Windows,即使用 BOOST_HAS_WINTHREADS的情况.thread类提供了两种构造函数:thread::thread()thread::thread(const func

Boost Thread学习笔记三

下面先对condition_impl进行简要分析.condition_impl在其构造函数中会创建两个Semaphore(信号量):m_gate.m_queue,及一个Mutex(互斥体,跟boost::mutex类似,但boost::mutex是基于CriticalSection<临界区>的):m_mutex,其中:m_queue相当于当前所有等待线程的等待队列,构造函数中调用CreateSemaphore来创建Semaphore时,lMaximumCount参数被指定为(std::nume

Boost Thread学习笔记四

barrierbarrier类的接口定义如下: 1 class barrier : private boost::noncopyable   // Exposition only 2 { 3 public: 4   // construct/copy/destruct 5   barrier(size_t n); 6   ~barrier(); 7  8   // waiting 9   bool wait();10 }; barrier类为我们提供了这样一种控制线程同步的机制:前n - 1次调

Boost Thread学习笔记五

多线程编程中还有一个重要的概念:Thread Local Store(TLS,线程局部存储),在boost中,TLS也被称作TSS,Thread Specific Storage.boost::thread库为我们提供了一个接口简单的TLS的面向对象的封装,以下是tss类的接口定义: class tss{public:    tss(boost::function1<void, void*>* pcleanup);    void* get() const;    void set(void*

C++ boost thread学习(一)

线程中断 在一个线程对象上调用 interrupt() 会中断相应的线程,并会在这个线程中抛出一个类型为 boost::thread_interrupted 的异常. 如果给定的线程不包含任何中断点,简单调用interrupt就不会起作用. 每当一个线程中断点,它就会检查interrupt是否被调用过.只有被调用过了, boost::thread_interrupted 异常才会相应地抛出. Boost.Thread定义了一系列的中断点,例如sleep() 函数,由于sleep() 在这个例子里

Jetty学习二:配置概览-怎么配置Jetty

Jetty POJO配置 Jetty的核心组件是Plain Old Java Objects(POJOs):配置Jetty的大部分工作就是在Jetty POJOs上的初始化.装配和设置域的处理,你能通过以下的方式来实现:  1)直接通过Java代码初始化和装配Jetty对象.这个在后面Embedding Jetty讲. 2)用Jetty XML配置(一个控制反转(IoC)框架)初始化和装配Jetty对象.etc/jetty.xml文件是基本的Jetty XML配置文件,但有一些其它的etc/je

boost::thread boost库线程

一.boost::thread的创建 1.线程创建方法一: boost::shared_ptr<boost::thread> writeThread_; boost::function0<void> f = boost::bind(&DBTaskMgr::execute, this); writeThread_ = boost::shared_ptr<boost::thread>(new boost::thread(f)); 2.线程创建方法二: boost::

boost asio 学习(六) 定时器

http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=7 6 定时器 boost::asio 提供了一个 deadline_timer class来提供同步与异步的接口. BOOST文档提供了一组优秀示例.第一个例子,将创建一个间隔5秒的定时器. #include <boost/asio.hpp> #include <boost/shared_ptr.hpp&