c – 为什么std :: queue不是线程安全的?
发布时间:2020-12-16 10:12:49 所属栏目:百科 来源:网络整理
导读:话题说明了这一点.我不明白为什么std :: queue(或者通常:任何队列)本质上不是线程安全的,当没有涉及其他数据结构的迭代器时. 根据共同的规则 至少有一个帖子写给… 另一个线程正在从共享资源中读取 我应该在以下示例代码中遇到冲突: #include "stdafx.h"#i
话题说明了这一点.我不明白为什么std :: queue(或者通常:任何队列)本质上不是线程安全的,当没有涉及其他数据结构的迭代器时.
根据共同的规则 >至少有一个帖子写给… 我应该在以下示例代码中遇到冲突: #include "stdafx.h" #include <queue> #include <thread> #include <iostream> struct response { static int & getCount() { static int theCount = 0; return theCount; } int id; }; std::queue<response> queue; // generate 100 response objects and push them into the queue void produce() { for (int i = 0; i < 100; i++) { response r; r.id = response::getCount()++; queue.push(r); std::cout << "produced: " << r.id << std::endl; } } // get the 100 first responses from the queue void consume() { int consumedCounter = 0; for (;;) { if (!queue.empty()) { std::cout << "consumed: " << queue.front().id << std::endl; queue.pop(); consumedCounter++; } if (consumedCounter == 100) break; } } int _tmain(int argc,_TCHAR* argv[]) { std::thread t1(produce); std::thread t2(consume); t1.join(); t2.join(); return 0; } 一切似乎都很好: 解决方法
想象一下,你检查!queue.empty(),进入下一个块,在进入queue.first()之前,另一个线程将删除(弹出)唯一的元素,因此你查询一个空队列.
使用如下所示的同步队列 #pragma once #include <queue> #include <mutex> #include <condition_variable> template <typename T> class SharedQueue { public: SharedQueue(); ~SharedQueue(); T& front(); void pop_front(); void push_back(const T& item); void push_back(T&& item); int size(); bool empty(); private: std::deque<T> queue_; std::mutex mutex_; std::condition_variable cond_; }; template <typename T> SharedQueue<T>::SharedQueue(){} template <typename T> SharedQueue<T>::~SharedQueue(){} template <typename T> T& SharedQueue<T>::front() { std::unique_lock<std::mutex> mlock(mutex_); while (queue_.empty()) { cond_.wait(mlock); } return queue_.front(); } template <typename T> void SharedQueue<T>::pop_front() { std::unique_lock<std::mutex> mlock(mutex_); while (queue_.empty()) { cond_.wait(mlock); } queue_.pop_front(); } template <typename T> void SharedQueue<T>::push_back(const T& item) { std::unique_lock<std::mutex> mlock(mutex_); queue_.push_back(item); mlock.unlock(); // unlock before notificiation to minimize mutex con cond_.notify_one(); // notify one waiting thread } template <typename T> void SharedQueue<T>::push_back(T&& item) { std::unique_lock<std::mutex> mlock(mutex_); queue_.push_back(std::move(item)); mlock.unlock(); // unlock before notificiation to minimize mutex con cond_.notify_one(); // notify one waiting thread } template <typename T> int SharedQueue<T>::size() { std::unique_lock<std::mutex> mlock(mutex_); int size = queue_.size(); mlock.unlock(); return size; } 对front()的调用会等到它有一个元素并锁定底层队列,因此一次只有一个线程可以访问它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |