• 条件变量


    条件变量是thread库提供的一种用于等待的同步机制,可以实现线程间的通信,它必须与互斥量配合使用,等待另一个线程中某个事件的发生(满足某个条件),然后线程才能继续执行。

    thread库提供两种条件变量对象condition_variable和condition_variable_any,一般情况下,我们应该使用condition_variable_any,它能够适用更广泛的互斥量类型。

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

    wait():当前线程调用wait()后将被阻塞,直到另外某个线程调用notify_*唤醒当前线程;当线程被阻塞时,该函数会自动调用std::mutex的unlock()释放锁,使得其它被阻塞在锁竞争上的线程得以继续执行。一旦当前线程获得通知(notify,通常是另外某个线程调用notify_*唤醒了当前线程),wait()函数也是自动调用std::mutex的lock()。

    生产者-消费者模式:

    #include <boost/thread.hpp>
    #include <boost/ref.hpp>
    #include <iostream>
    #include <stack>
    
    boost::mutex io_mu;
    class buffer
    {
    private:
    	boost::mutex mu; // 互斥量,配合条件变量使用
    	boost::condition_variable_any cond_put; // 写条件变量
    	boost::condition_variable_any cond_get; // 读条件变量
    	std::stack<int> stk; // 缓冲区对象
    	int un_read, capaccity; 
    	bool is_full() // 缓冲区满判断
    	{
    		return un_read == capaccity;
    	}
    	bool is_empty() // 缓冲区空判断
    	{
    		return stk.size() == 0;
    	}
    public:
    	buffer(std::size_t n) :un_read(0), capaccity(n){}
    	void put(int x) // 写数据
    	{
    		{ // 开始一个局部域
    			boost::mutex::scoped_lock lock(mu); // 锁定互斥量
    			while (is_full()) // 检查缓冲区是否满
    			{
    				{ // 局部域,锁定io_mu
    					boost::mutex::scoped_lock lock(io_mu);
    					std::cout << "full waiting..." << std::endl;
    				}
    				cond_put.wait(mu); // 条件变量等待
    			} // 条件满足,停止等待
    			stk.push(x); // 压栈,写入数据
    			++un_read;
    		} // 通知前解锁互斥量,条件变量的通知不需要互斥量锁定
    		cond_get.notify_one(); // 通知可以读数据
    	}
    
    	void get(int *x) // 读数据
    	{
    		{ // 局部域开始
    			boost::mutex::scoped_lock lock(mu); // 锁定互斥量
    			while (is_empty()) // 检查缓冲区是否空
    			{
    				{ // 锁定io_mu
    					boost::mutex::scoped_lock lock(io_mu);
    					std::cout << "empty waiting..." << std::endl;
    				}
    				cond_get.wait(mu); // 条件变量等待
    			} // 条件满足,停止等待
    			--un_read;
    			*x = stk.top(); // 读取数据
    			stk.pop();
    		} // 通知前解锁
    		cond_put.notify_one();
    	}
    };
    
    buffer buf(5); // 定义一个缓冲区对象
    void producer(int n) // 生产者
    {
    	for (int i = 0; i < n; ++i)
    	{
    		{
    			boost::mutex::scoped_lock lock(io_mu);
    			std::cout << "put: " << i << std::endl;
    		}
    		buf.put(i); // 写入数据
    	}
    }
    
    void consumer(int n) // 消费者
    {
    	int x;
    	for (int i = 0; i < n; ++i)
    	{
    		{
    			buf.get(&x); // 读取数据
    			boost::mutex::scoped_lock lock(io_mu);
    			std::cout << "get: " << x << std::endl;
    		}
    	}
    }
    
    int main()
    {
    
    	boost::thread t1(producer, 20);
    	boost::thread t2(consumer, 10);
    	boost::thread t3(consumer, 10);
    	t1.join();
    	t2.join();
    	t3.join();
    	return 0;
    }
    

      

    运行截图:

  • 相关阅读:
    jQuery基础开发详解 重要
    Jquery插件form和cookie
    javascript keycode大全
    用户体验一些链接
    SQL导入Excel数据时,数字中混有字符将导致数据丢失的解决办法
    列出本机所有固定驱动器和可移动驱动器
    ADOQUERY,CLIENTDATASET,ADOSTOREPROC执行存储过程【多种方法】
    如何发布 JSON 项目?[转橙子]
    ADOQUERY,CLIENTDATASET,ADOSTOREPROC执行存储过程【多种方法】
    ADOQUERY,CLIENTDATASET,ADOSTOREPROC执行存储过程【多种方法】
  • 原文地址:https://www.cnblogs.com/ACGame/p/9102241.html
Copyright © 2020-2023  润新知