使用条件变量构建线程安全队列

当等待线程重新获取互斥量并检查条件时,如果它并非直接响应另一个线程的通知,这就是所谓的伪唤醒(spurious wakeup),也叫虚假唤醒。

使用条件变量的线程安全队列(完整版)

点击查看代码
template<typename T>
class threadSafeQueue
{
public:
	threadSafeQueue(){}
	threadSafeQueue(const threadSafeQueue& other)
	{
		lock_guard<mutex>lock(other.m_mutex);
		m_queue = other.m_queue;
	}
	void push(T value)
	{
		lock_guard<mutex>lock(m_mutex);
		m_queue.push(value);
		m_conditionVar.notify_one();//发送通知
		cout << "push notify...\n";
	}
	void waitAndPop(T& value)
	{
		unique_lock<mutex>lock(m_mutex);
      
      	//检测条件,如果为假就释放互斥量,并阻塞该线程,直到接收到通知使条件为真
		m_conditionVar.wait(lock, [this]
			{
				cout << "waiting...\n";
				return !m_queue.empty();
			}
		);
      
		cout << "end waiting...\n";
		value = m_queue.front();
		m_queue.pop();
	}
	shared_ptr<T> waitAndPop()
	{
		unique_lock<mutex>lock(m_mutex);
		m_conditionVar.wait(lock, [this]
			{
				return !m_queue.empty();
			}
		);
		shared_ptr<T>ret(make_shared<T>(m_queue.front()));
		m_queue.pop();
		return ret;
	}
	bool tryPop(T& value)
	{
		lock_guard<mutex>lock(m_mutex);
		if (m_queue.empty())
		{
			return false;
		}
		value = m_queue.front();
		m_queue.pop();
		return true;
	}
	shared_ptr<T> tryPop()
	{
		lock_guard<mutex>lock(m_mutex);
		if (m_queue.empty())
		{
			return shared_ptr<T>();
		}
		shared_ptr<T>ret(make_shared<T>(m_queue.front()));
		m_queue.pop();
		return ret;
	}
	bool empty()const
	{
		lock_guard<mutex>lock(m_mutex);
		return m_queue.empty();
	}
private:
	mutable mutex m_mutex;
	queue<T>m_queue;
	condition_variable m_conditionVar;
};

示例用法:

点击查看代码
	threadSafeQueue<int>q;
	thread t([&q]
		{
			int value = 0;
			q.waitAndPop(value);
			cout << value << endl;
		}
	);
	thread t2([&q]
		{
			q.push(999);
		}
	);
	t.join();
	t2.join();

运行结果:

或者是这样

因为线程执行顺序不确定

posted @ 2021-09-12 17:24  youlj  阅读(42)  评论(0)    收藏  举报