前言
在多线程场景下,我们可以使用锁、条件变量以及信号量来解决同步问题。而使用线程安全的消息队列几乎可以解决绝大部分开发问题。
golang中可以使用channel,c++则需要我们自己来造轮子。最近项目有用到,因此实现了一个简单的消息队列。
代码
#include <mutex>
#include <condition_variable>
#include <queue>
template<typename T>
class MsgQueue {
private:
std::deque<T> q_;
std::mutex mtx_;
std::condition_variable cdv_;
public:
// 传入一条消息,队列长度未做限制
void push(T data) {
std::unique_lock<std::mutex> lock(mtx_);
q_.push_back(data);
cdv_.notify_one(); //唤醒一个阻塞的线程
}
// 获取一个消息,若队列为空,则阻塞等待
T pop() {
std::unique_lock<std::mutex> lock(mtx_);
while (q_.empty())
{
cdv_.wait(lock);
}
auto ret = std::move(q_.front());
q_.pop_front();
return ret;
}
// 获取队列长度
size_t size() {
std::unique_lock<std::mutex> lock(mtx_);
return q_.size();
}
};
开源项目
若简单实现的消息队列无法满足要求,还有一些比较出名的c++开源项目可供选择。
concurrentqueue 是一个 C++的工业级无锁队列。对使用者而言值得注意的特性如下:
- 完全线程安全的无锁队列。从任意数量的线程并发使用。
- 不需要编译。该项目是一堆头文件,只需要将头文件放入项目中就可以使用。
- 不保证消息顺序的一致性!对消息顺序有要求的话不可使用该队列。
MPMCQueue 是用 C++11 编写的有界多生产者多消费者并发队列。