MPSC队列
AI实现 尚未人工认证测试
1. 基于互斥锁和条件变量的实现(最常用)
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <optional>
#include <chrono>
#include <memory>
template<typename T>
class MPSCQueue {
public:
explicit MPSCQueue(size_t capacity = 0)
: capacity_(capacity), is_closed_(false) {}
~MPSCQueue() {
close();
}
// 生产者:推送数据(阻塞直到成功或超时)
template<typename U>
bool push(U&& item, std::chrono::milliseconds timeout = std::chrono::milliseconds(0)) {
std::unique_lock<std::mutex> lock(mutex_);
// 如果有容量限制,等待队列有空闲空间
if (capacity_ > 0) {
if (timeout.count() > 0) {
if (!not_full_.wait_for(lock, timeout, [this]() {
return queue_.size() < capacity_ || is_closed_;
})) {
return false; // 超时
}
} else {
not_full_.wait(lock, [this]() {
return queue_.size() < capacity_ || is_closed_;
});
}
}
if (is_closed_) return false;
queue_.push(std::forward<U>(item));
lock.unlock();
not_empty_.notify_one();
return true;
}
// 生产者:尝试推送数据(非阻塞)
template<typename U>
bool try_push(U&& item) {
std::unique_lock<std::mutex> lock(mutex_, std::try_to_lock);
if (!lock.owns_lock()) return false;
if (is_closed_ || (capacity_ > 0 && queue_.size() >= capacity_)) {
return false;
}
queue_.push(std::forward<U>(item));
lock.unlock();
not_empty_.notify_one();
return true;
}
// 消费者:弹出数据(阻塞直到有数据或队列关闭)
std::optional<T> pop(std::chrono::milliseconds timeout = std::chrono::milliseconds(0)) {
std::unique_lock<std::mutex> lock(mutex_);
if (timeout.count() > 0) {
if (!not_empty_.wait_for(lock, timeout, [this]() {
return !queue_.empty() || is_closed_;
})) {
return std::nullopt; // 超时
}
} else {
not_empty_.wait(lock, [this]() {
return !queue_.empty() || is_closed_;
});
}
if (queue_.empty()) return std::nullopt;
T item = std::move(queue_.front());
queue_.pop();
lock.unlock();
if (capacity_ > 0) {
not_full_.notify_one();
}
return std::move(item);
}
// 消费者:尝试弹出数据(非阻塞)
std::optional<T> try_pop() {
std::unique_lock<std::mutex> lock(mutex_, std::try_to_lock);
if (!lock.owns_lock() || queue_.empty()) {
return std::nullopt;
}
T item = std::move(queue_.front());
queue_.pop();
lock.unlock();
if (capacity_ > 0) {
not_full_.notify_one();
}
return std::move(item);
}
// 关闭队列,唤醒所有等待的线程
void close() {
{
std::lock_guard<std::mutex> lock(mutex_);
is_closed_ = true;
}
not_empty_.notify_all();
not_full_.notify_all();
}
// 队列是否已关闭
bool is_closed() const {
return is_closed_.load(std::memory_order_acquire);
}
// 获取队列大小
size_t size() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.size();
}
// 队列是否为空
bool empty() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.empty();
}
private:
mutable std::mutex mutex_;
std::condition_variable not_empty_;
std::condition_variable not_full_;
std::queue<T> queue_;
const size_t capacity_;
std::atomic<bool> is_closed_;
};
2. 无锁实现(更高性能)
#include <atomic>
#include <memory>
#include <optional>
// 无锁MPSC队列节点
template<typename T>
struct LockFreeNode {
T data;
std::atomic<LockFreeNode<T>*> next;
explicit LockFreeNode(T&& val)
: data(std::move(val)), next(nullptr) {}
explicit LockFreeNode(const T& val)
: data(val), next(nullptr) {}
};
template<typename T>
class LockFreeMPSCQueue {
public:
LockFreeMPSCQueue() {
// 创建dummy节点
auto dummy = new LockFreeNode<T>(T{});
head_.store(dummy, std::memory_order_relaxed);
tail_.store(dummy, std::memory_order_relaxed);
}
~LockFreeMPSCQueue() {
// 清理所有节点
while (auto node = head_.load(std::memory_order_relaxed)) {
head_.store(node->next.load(std::memory_order_relaxed), std::memory_order_relaxed);
delete node;
}
}
// 生产者:推送数据(无锁)
template<typename U>
void push(U&& item) {
auto new_node = new LockFreeNode<T>(std::forward<U>(item));
// 获取当前tail
auto tail = tail_.load(std::memory_order_relaxed);
// CAS循环直到成功
LockFreeNode<T>* expected = nullptr;
do {
expected = nullptr;
tail = tail_.load(std::memory_order_relaxed);
} while (!tail->next.compare_exchange_weak(
expected,
new_node,
std::memory_order_release,
std::memory_order_relaxed));
// 更新tail
tail_.store(new_node, std::memory_order_release);
}
// 消费者:弹出数据
std::optional<T> pop() {
auto head = head_.load(std::memory_order_relaxed);
auto next = head->next.load(std::memory_order_acquire);
if (next == nullptr) {
return std::nullopt;
}
// 获取数据
T data = std::move(next->data);
// 更新head
head_.store(next, std::memory_order_release);
// 删除旧节点
delete head;
return std::move(data);
}
// 队列是否为空
bool empty() const {
auto head = head_.load(std::memory_order_acquire);
return head->next.load(std::memory_order_acquire) == nullptr;
}
private:
alignas(64) std::atomic<LockFreeNode<T>*> head_; // 消费者使用
alignas(64) std::atomic<LockFreeNode<T>*> tail_; // 生产者使用
};
3. 环形缓冲区实现(固定大小,高性能)
#include <vector>
#include <atomic>
#include <optional>
#include <thread>
template<typename T>
class RingBufferMPSCQueue {
public:
explicit RingBufferMPSCQueue(size_t capacity)
: capacity_(capacity),
buffer_(capacity),
head_(0),
tail_(0) {
// 确保容量是2的幂,便于使用位运算
if ((capacity & (capacity - 1)) != 0) {
throw std::invalid_argument("Capacity must be power of two");
}
}
// 生产者:推送数据
template<typename U>
bool push(U&& item) {
const auto current_tail = tail_.load(std::memory_order_relaxed);
const auto next_tail = increment(current_tail);
// 检查是否已满
if (next_tail == head_.load(std::memory_order_acquire)) {
return false; // 队列已满
}
// 写入数据
buffer_[current_tail & (capacity_ - 1)] = std::forward<U>(item);
// 发布写入
std::atomic_thread_fence(std::memory_order_release);
tail_.store(next_tail, std::memory_order_release);
return true;
}
// 生产者:批量推送
template<typename Iterator>
size_t push_bulk(Iterator begin, Iterator end) {
size_t count = 0;
for (auto it = begin; it != end; ++it) {
if (!push(std::move(*it))) {
break;
}
++count;
}
return count;
}
// 消费者:弹出数据
std::optional<T> pop() {
const auto current_head = head_.load(std::memory_order_relaxed);
// 检查是否为空
if (current_head == tail_.load(std::memory_order_acquire)) {
return std::nullopt;
}
// 读取数据
T item = std::move(buffer_[current_head & (capacity_ - 1)]);
// 发布读取
std::atomic_thread_fence(std::memory_order_release);
head_.store(increment(current_head), std::memory_order_release);
return std::move(item);
}
// 消费者:批量弹出
template<typename OutputIterator>
size_t pop_bulk(OutputIterator output, size_t max_count) {
size_t count = 0;
while (count < max_count) {
auto item = pop();
if (!item) break;
*output++ = std::move(*item);
++count;
}
return count;
}
// 队列是否为空
bool empty() const {
return head_.load(std::memory_order_acquire) ==
tail_.load(std::memory_order_acquire);
}
// 队列是否已满
bool full() const {
const auto current_tail = tail_.load(std::memory_order_acquire);
return increment(current_tail) == head_.load(std::memory_order_acquire);
}
// 队列大小
size_t size() const {
const auto head = head_.load(std::memory_order_acquire);
const auto tail = tail_.load(std::memory_order_acquire);
return (tail - head) & (capacity_ - 1);
}
private:
size_t increment(size_t index) const {
return (index + 1) & (capacity_ - 1);
}
const size_t capacity_;
std::vector<T> buffer_;
alignas(64) std::atomic<size_t> head_; // 消费者使用
alignas(64) std::atomic<size_t> tail_; // 生产者使用
};
4. 使用示例
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
void test_mpsc_queue() {
// 测试有锁版本
MPSCQueue<int> queue(100); // 容量100
std::atomic<int> producer_count{0};
std::atomic<int> consumer_count{0};
// 启动多个生产者
std::vector<std::thread> producers;
for (int i = 0; i < 3; ++i) {
producers.emplace_back([i, &queue, &producer_count]() {
for (int j = 0; j < 100; ++j) {
int value = i * 100 + j;
if (queue.push(value)) {
producer_count.fetch_add(1, std::memory_order_relaxed);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
});
}
// 启动单个消费者
std::thread consumer([&queue, &consumer_count]() {
while (true) {
auto item = queue.pop(std::chrono::milliseconds(100));
if (!item) {
// 检查是否所有生产者都结束了
if (queue.is_closed()) break;
continue;
}
consumer_count.fetch_add(1, std::memory_order_relaxed);
// 处理数据
// std::cout << "Consumed: " << *item << std::endl;
}
});
// 等待生产者结束
for (auto& t : producers) {
t.join();
}
// 关闭队列
queue.close();
// 等待消费者结束
consumer.join();
std::cout << "Produced: " << producer_count << std::endl;
std::cout << "Consumed: " << consumer_count << std::endl;
}
void test_lockfree_mpsc_queue() {
// 测试无锁版本
LockFreeMPSCQueue<int> queue;
std::vector<std::thread> producers;
for (int i = 0; i < 3; ++i) {
producers.emplace_back([i, &queue]() {
for (int j = 0; j < 100; ++j) {
queue.push(i * 100 + j);
}
});
}
// 等待生产者
for (auto& t : producers) {
t.join();
}
// 消费者消费所有数据
int count = 0;
while (auto item = queue.pop()) {
++count;
}
std::cout << "Lock-free queue consumed: " << count << " items" << std::endl;
}
int main() {
std::cout << "Testing MPSC Queue with locks:" << std::endl;
test_mpsc_queue();
std::cout << "\nTesting Lock-free MPSC Queue:" << std::endl;
test_lockfree_mpsc_queue();
return 0;
}
5. 性能优化建议
-
缓存行对齐:
- 使用
alignas(64)防止生产者之间的false sharing
- 使用
-
内存分配优化:
// 使用内存池预分配节点 template<typename T> class PooledMPSCQueue { // 实现节点池 }; -
批量操作:
- 提供
push_bulk和pop_bulk减少锁开销
- 提供
-
选择合适的实现:
- 低竞争场景:有锁队列简单可靠
- 高吞吐场景:无锁队列性能更好
- 固定大小需求:环形缓冲区最快
6. 测试代码
#include <iostream>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <iomanip>
#include <algorithm>
#include <random>
// 包含我们之前实现的三种队列
#include "MPSC/MPSCQueue.h" // 有锁队列
#include "MPSC/LockFreeMPSCQueue.h" // 无锁队列
#include "MPSC/RingBufferMPSCQueue.h"// 环形缓冲区队列
using namespace std::chrono;
// ================= 性能测试 =================
template<typename Queue>
double test_MPSCqueue(int producers, int items_per_producer) {
Queue queue;
std::atomic<int> produced{0};
std::atomic<int> consumed{0};
std::atomic<bool> stop{false};
// 启动生产者
std::vector<std::thread> producer_threads;
for (int i = 0; i < producers; ++i) {
producer_threads.emplace_back([&, i]() {
for (int j = 0; j < items_per_producer; ++j) {
int value = i * items_per_producer + j;
// queue.push(value);
while (!queue.push(value)) {
std::this_thread::yield();
}
produced.fetch_add(1, std::memory_order_relaxed);
}
});
}
// 启动消费者
std::thread consumer([&]() {
while (consumed < producers * items_per_producer) {
auto item = queue.pop();
if (item) {
consumed.fetch_add(1, std::memory_order_relaxed);
} else {
std::this_thread::yield();
}
}
stop = true;
});
// 计时
auto start = high_resolution_clock::now();
// 等待生产者
for (auto& t : producer_threads) {
t.join();
}
// 等待消费者
consumer.join();
auto end = high_resolution_clock::now();
double total_time = duration_cast<nanoseconds>(end - start).count() / 1e9;
double total_items = producers * items_per_producer;
return total_items / total_time; // 返回吞吐量 (items/sec)
}
template<typename Queue>
double test_LOCKFreequeue(int producers, int items_per_producer) {
Queue queue;
std::atomic<int> produced{0};
std::atomic<int> consumed{0};
std::atomic<bool> stop{false};
// 启动生产者
std::vector<std::thread> producer_threads;
for (int i = 0; i < producers; ++i) {
producer_threads.emplace_back([&, i]() {
for (int j = 0; j < items_per_producer; ++j) {
int value = i * items_per_producer + j;
queue.push(value);
// while (!queue.push(value)) {
// std::this_thread::yield();
// }
produced.fetch_add(1, std::memory_order_relaxed);
}
});
}
// 启动消费者
std::thread consumer([&]() {
while (consumed < producers * items_per_producer) {
auto item = queue.pop();
if (item) {
consumed.fetch_add(1, std::memory_order_relaxed);
} else {
std::this_thread::yield();
}
}
stop = true;
});
// 计时
auto start = high_resolution_clock::now();
// 等待生产者
for (auto& t : producer_threads) {
t.join();
}
// 等待消费者
consumer.join();
auto end = high_resolution_clock::now();
double total_time = duration_cast<nanoseconds>(end - start).count() / 1e9;
double total_items = producers * items_per_producer;
return total_items / total_time; // 返回吞吐量 (items/sec)
}
template<typename Queue>
double test_RINGBUfferqueue(int producers, int items_per_producer) {
Queue queue{2048};
std::atomic<int> produced{0};
std::atomic<int> consumed{0};
std::atomic<bool> stop{false};
// 启动生产者
std::vector<std::thread> producer_threads;
for (int i = 0; i < producers; ++i) {
producer_threads.emplace_back([&, i]() {
for (int j = 0; j < items_per_producer; ++j) {
int value = i * items_per_producer + j;
while (!queue.push(value)) {
std::this_thread::yield();
}
produced.fetch_add(1, std::memory_order_relaxed);
}
});
}
// 启动消费者
std::thread consumer([&]() {
while (consumed < producers * items_per_producer) {
auto item = queue.pop();
if (item) {
consumed.fetch_add(1, std::memory_order_relaxed);
} else {
std::this_thread::yield();
}
}
stop = true;
});
// 计时
auto start = high_resolution_clock::now();
// 等待生产者
for (auto& t : producer_threads) {
t.join();
}
// 等待消费者
consumer.join();
auto end = high_resolution_clock::now();
double total_time = duration_cast<nanoseconds>(end - start).count() / 1e9;
double total_items = producers * items_per_producer;
return total_items / total_time; // 返回吞吐量 (items/sec)
}
int main() {
std::cout << "========== MPSC队列简单性能测试 ==========\n";
std::cout << "测试配置: 4个生产者,每个生产10万个项目\n\n";
const int PRODUCERS = 4;
const int ITEMS_PER_PRODUCER = 100000;
std::cout << std::fixed << std::setprecision(2);
try {
// 测试有锁队列
std::cout << "1. 测试有锁队列...\n";
double locked_throughput = test_MPSCqueue<MPSCQueue<int>>(PRODUCERS, ITEMS_PER_PRODUCER);
std::cout << " 吞吐量: " << locked_throughput / 1000 << " K items/sec\n\n";
// 测试无锁队列
std::cout << "2. 测试无锁队列...\n";
/* 可能存在死锁 */
double lockfree_throughput = test_LOCKFreequeue<LockFreeMPSCQueue<int>>(PRODUCERS, ITEMS_PER_PRODUCER);
std::cout << " 吞吐量: " << lockfree_throughput / 1000 << " K items/sec\n\n";
// // 测试环形缓冲区队列
// std::cout << "3. 测试环形缓冲区队列...\n";
double ringbuffer_throughput = test_RINGBUfferqueue<RingBufferMPSCQueue<int>>(PRODUCERS, ITEMS_PER_PRODUCER);
std::cout << " 吞吐量: " << ringbuffer_throughput / 1000 << " K items/sec\n\n";
// 性能对比
std::cout << "========== 性能对比 ==========\n";
std::cout << std::setw(20) << "队列类型"
<< std::setw(20) << "吞吐量(K/s)"
<< std::setw(20) << "相对性能" << "\n";
std::cout << std::string(60, '-') << "\n";
double max_throughput = std::max({lockfree_throughput, locked_throughput,ringbuffer_throughput});
// std::max({locked_throughput} /* ringbuffer_throughput}*/);
auto print_row = [&](const std::string& name, double throughput) {
std::cout << std::setw(20) << name
<< std::setw(20) << throughput / 1000
<< std::setw(20) << (throughput / max_throughput * 100) << "%\n";
};
print_row("有锁队列", locked_throughput);
print_row("无锁队列", lockfree_throughput);
print_row("环形缓冲区", ringbuffer_throughput);
std::cout << "\n";
// 结论
// std::cout << "========== 结论 ==========\n";
// if (ringbuffer_throughput > lockfree_throughput && ringbuffer_throughput > locked_throughput) {
// std::cout << "✓ 环形缓冲区性能最佳,适合MPSC场景\n";
// } else if (lockfree_throughput > locked_throughput) {
// std::cout << "✓ 无锁队列性能较好,适合高并发场景\n";
// } else {
// std::cout << "✓ 有锁队列简单可靠,适合低并发场景\n";
// }
} catch (const std::exception& e) {
std::cerr << "测试错误: " << e.what() << std::endl;
return 1;
}
return 0;
}

浙公网安备 33010602011771号