boost并发编程(二)——条件变量

本文详细解析了一个使用条件变量实现缓冲区读写的并发程序,包括代码解释、关键逻辑及其实现过程,深入探讨了互斥锁与条件变量在解决线程同步问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       直接贴代码吧:

class buffer
{
	private:
		mutex mu, io_mu;
		condition_variable_any cond_get, cond_put;
		std::stack<int> stk;
		int un_read, capacity;

		bool is_full()
		{
			return un_read == capacity;
		}

		bool is_empty()
		{
			return un_read == 0;
		}

	public:
		buffer(size_t n):un_read(0), capacity(n){}

		void put(int x)
		{
			{
				mutex::scoped_lock lock(mu);

				while(is_full())
				{
					{
						mutex::scoped_lock lock(io_mu);
						std::cout << "full waiting..." << std::endl;
					}

					cond_put.wait(mu);
				}

				stk.push(x);

				{
					mutex::scoped_lock lock(io_mu);
					std::cout << "put " << x << std::endl;
				}

				++un_read;
			}

			cond_get.notify_one();
		}

		void get(int& x)
		{
			{
				mutex::scoped_lock lock(mu);

				while(is_empty())
				{
					{
						mutex::scoped_lock lock(io_mu);
						std::cout << "empty waiting..." << std::endl;
					}

					cond_get.wait(mu);
				}

				--un_read;
				x = stk.top();

				{
					mutex::scoped_lock lock(io_mu);
					std::cout << "get " << x << std::endl;
				}

				stk.pop();
			}

			cond_put.notify_one();
		}
};

void producer(int n, buffer& buf)
{
	for(int i = 0; i < n; ++i)
	{
		buf.put(i);
	}
}

void consumer(int n, buffer& buf)
{
	int x;

	for(int i = 0; i < n; ++i)
	{
		buf.get(x);
	}
}

int main()
{
   buffer buf(5);

   thread t1(producer, 20, ref(buf));
   thread t2(consumer, 10, ref(buf));
   thread t3(consumer, 10, ref(buf));

   t1.join();
   t2.join();
   t3.join();

   return 0;
}

        代码其实不复杂,我来解释一下逻辑。mutex变量使用简单方便,但只提供较粗糙的互斥锁,对所有进程一视同仁,而在某些情况下需要对进程进行区别。比如这个例子,缓冲区读写问题,如果缓冲区满就应该停止写入,禁止生产者线程运行,运行消费者线程读取数据;反之,若缓冲区为空,则禁止消费者线程运行,运行生产者线程生产数据。mutex变量就没有这种灵活性,这时应该使用条件变量——condition_variable_any类对象。它会做什么呢?举例来说,当在生产者线程中检测到缓冲区已满时,调用生产者线程对应的condition_variable_any类对象cond_put的wait()方法,就会阻塞当前线程,同时解锁其参数代表的mutex互斥量,以使消费者线程能运行;相应的,当生产了数据后,调用消费者线程对应的条件变量cond_get的notify_one()方法唤醒某个被阻塞的(如果有)消费者线程来读取数据。
        main()函数中thread对象接受的参数是通过值传递的,如果需要传递引用,需要用ref对象包装。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值