对std::队列的pop和push操作使用单独的互斥锁,而不是一个互斥锁
Using separate mutexs for pop and push operatin of std::queue instead of one
假设有一个生产者和多个消费者使用std::queue
,为了保护std::queue
中的数据,在访问std::queue
时必须使用互斥锁
但是如果使用两个单独的锁呢?一个是pop
,一个是push
?我认为使用两个单独的锁可能会更快。
我看了STL源代码。std::queue
默认由std::deque
实现。pop_front()
和push_back()
使用两个独立的迭代器访问数据,一个用于第一个元素,一个用于最后一个元素。
void push_front(const value_type& __x){
if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first){
this->_M_impl.construct(this->_M_impl._M_start._M_ur - 1, __x);
} else {
_M_push_front_aux(__x);
}
}
void push_back(){
if (this->_M_impl._M_finish._M_cur != this->_M_impl._M_finish._M_first){
this->_M_impl.construct(this->_M_impl._M_finish._M_ur - 1, __x);
} else {
_M_pop_back_aux();
}
}
因此,当一个线程正在pop
队列中时,另一个线程会插队并尝试push_back
。因为这两个操作使用不同的迭代器,指向deque
的两个不同的结束点,所以这两个操作似乎都没问题?
pop_front
和push_back
可能在内部访问不同的迭代器,但这就是抽象的全部意义:您不能确定这一点,而且不允许依赖它。
并且,正如已经在评论中指出的那样,还有size
,这是由于c++ 11需要在O(1)
中执行。为了满足这个要求,push_back
和pop_front
都需要改变一些内部存储的大小,这是你肯定有竞争条件的地方。
然后想想当你的队列空了会发生什么…
总之:不要那样做。在并发设置中使用std::queue
,你需要一个互斥锁来保护它。
作为另一种选择,您应该查看无锁数据结构。
相关文章:
- Howo 使用 cl 预处理为 masm 组装生成一个单独的文件
- 显示数组的问题.一切都放在一个单独的行中,但不放入单独的列中
- 如何在这个交换函数(一个单独的链表)中找到错误
- 如何将正则表达式中组的每次迭代都作为一个单独的组
- 如何将我的C++DLL包含在一个单独的项目中
- 元编程:函数定义的失败定义了一个单独的函数
- 每个方法都在一个单独的文件c++中
- 使用websockettpp库在多线程程序中为endpoint.listen()创建一个单独的提升线程
- C++-释放在main中分配但指向一个单独类的内存
- 读取整数文件并将每一行存储在一个单独的数组中
- 隔离易崩溃(SEGV),但将关键的遗留代码加速到一个单独的二进制文件中
- 如何用C++/OSX打开一个单独的程序
- 将指针设置为一个值加上一个单独的值
- 为什么您必须声明/创建一个单独的变量来通过引用调用,而不仅仅是在函数调用中创建一个自动对象
- 如何决定是否为窗口的小部件创建一个单独的类
- 如何调用一个函数,它在一个单独的类中打印出一个结构体数组
- 使用make将.o文件移动到一个单独的目录
- 如何从一个线程发出信号,并将信号与一个单独的函数连接起来
- Boost::为每个客户端创建一个单独的数组
- 在一个单独的线程中管理OpenGL上下文