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


    运行结果: 
    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 
  • 相关阅读:
    第三章 函数式编程中的异常处理
    第二章 函数式数据结构
    android 轮播图
    模仿qq列表信息滑动删除效果
    android绘制圆形图片的两种方式
    android图片验证码--自绘控件
    MPAndroidChart 3.0——LineChart(折线图)
    提交本地项目到github服务器
    android 帧动画,补间动画,属性动画的简单总结
    android AsynTask处理返回数据和AsynTask使用get,post请求
  • 原文地址:https://www.cnblogs.com/fire909090/p/6801543.html
Copyright © 2020-2023  润新知