欢迎您访问新疆栾骏商贸有限公司,公司主营电子五金轴承产品批发业务!
全国咨询热线: 400-8878-609

新闻资讯

技术学院

c++怎么实现一个线程安全的队列_c++中线程安全队列的实现思路与代码示例

作者:冰火之心2025-11-21 00:00:00
线程安全队列通过互斥锁和条件变量实现,支持多线程并发访问。1. 使用 std::mutex 保护共享数据,防止数据竞争;2. 利用 std::condition_variable 在队列为空时阻塞消费者,避免忙等;3. push 操作后通知等待线程,确保及时唤醒;4. 提供阻塞(wait_and_pop)与非阻塞(try_pop)两种出队方式,适应不同场景;5. 所有公共方法均加锁,保证操作原子性。该设计高效支持生产者-消费者模型。

在多线程编程中,多个线程同时访问共享数据结构(如队列)时容易引发数据竞争。为了保证线程安全,需要对队列的操作进行同步控制。C++ 中可以通过互斥锁(std::mutex)和条件变量(std::condition_variable)来实现一个线程安全的队列。

线程安全队列的基本设计思路

一个线程安全的队列需要满足以下几点:

  • 多个生产者线程可以安全地向队列添加元素。
  • 多个消费者线程可以安全地从队列取出元素。
  • 当队列为空时,消费者线程应阻塞等待,直到有新元素入队。
  • 使用互斥锁保护共享数据,防止并发访问导致的数据不一致。
  • 使用条件变量通知等待线程,避免忙等,提高效率。

代码实现示例

#include 
#include 
#include 
#include 
#include 

template
class ThreadSafeQueue {
private:
    std::queue data_queue;
    mutable std::mutex mtx;
    std::condition_variable cv;

public:
    ThreadSafeQueue() = default;

    void push(T value) {
        std::lock_guard lock(mtx);
        data_queue.push(std::move(value));
        cv.notify_one(); // 唤醒一个等待的消费者
    }

    bool try_pop(T& value) {
        std::lock_guard lock(mtx);
        if (data_queue.empty()) {
            return false;
        }
        value = std::move(data_queue.front());
        data_queue.pop();
        return true;
    }

    void wait_and_pop(T& value) {
        std::unique_lock lock(mtx);
        cv.wait(lock, [this] { return !data_queue.empty(); });
        value = std::move(data_queue.front());
        data_queue.pop();
    }

    bool empty() const {
        std::lock_guard lock(mtx);
        return data_queue.empty();
    }

    size_t size() const {
        std::lock_guard lock(mtx);
        return data_queue.size();
    }
};

使用示例

下面是一个简单的多线程使用场景,一个生产者线程不断入队,两个消费者线程从中取数据:

int main() {
    ThreadSafeQueue queue;

    auto producer = [&]() {
        for (int i = 0; i < 10; ++i) {
            queue.push(i);
            std::cout << "Produced: " << i << "\n";
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    };

    auto consumer = [&](int id) {
        for (int i = 0; i < 5; ++i) {
            int value;
            queue.wait_and_pop(value);
            std::cout << "Consumer " << id << " got: " << value << "\n";
        }
    };

    std::thread p(producer);
    std::thread c1(consumer, 1);
    std::thread c2(consumer, 2);

    p.join();
    c1.join();
    c2.join();

    return 0;
}

关键点说明

push() 使用 lock_guard 自动加锁,插入后调用 notify_one() 唤醒一个等待线程;wait_and_pop() 使用 unique_lock 配合 condition_variable 实现阻塞等待;try_pop() 提供非阻塞版本,适用于不想等待的场景。

该实现是通用、高效且线程安全的,适用于大多数生产者-消费者模型。

基本上就这些。