我在 C ++ 应用程序中有一个deque
指针。我知道有两个线程来访问它。
Thread1 将从后面添加指针, Thread2 将处理并从前面删除指针。
Thread2 会等到deque
达到一定金额,说出10个项目,然后开始处理它。它一次只能循环和处理10个项目。与此同时, Thread1 仍可能继续在双端队列中添加新项目。
我认为没有同步 deque
会很好,因为 Thread1 和 Thread2 正在访问{{的不同部分1}}。它是deque
而不是deque
。因此,不会重新分配vector
的现有内存。
我是对的吗?如果没有,为什么(我想知道我错过了什么)?
修改
我知道总是要同步它不会有什么坏处。但它可能会损害性能或不必要。我希望它尽可能快地运行。
答案 0 :(得分:4)
deque必须跟踪它有多少元素以及这些元素的位置。添加元素会更改存储的数据,删除元素也是如此。在没有同步的情况下从两个线程更改数据是数据竞争,并产生未定义的行为。
简而言之,必须同步这些操作。
答案 1 :(得分:2)
一般情况下,不能假定标准库容器是线程安全的,除非你所做的就是从中读取它们。
如果您在deque
实施后查看封面,您将发现类似的内容:
template <typename T>
class deque {
public:
private:
static size_t const BufferCapacity = /**/;
size_t _nb_available_buffer;
size_t _first_occupied_buffer;
size_t _last_occupied_buffer;
size_t _size_first_buffer;
size_t _size_last_buffer;
T** _buffers; // heap allocated array of
// heap allocated arrays of fixed capacity
}; // class deque
你看到了问题吗? _buffers
,至少可以通过enqueue和dequeue操作同时访问(特别是当数组变得太小而需要在更大的数组中复制时)。
那么,替代方案是什么?您正在寻找的是并发队列。有一些实现,除非它被证明是一个瓶颈,否则你可能不会过分担心它们是否无锁。一个例子是TTB concurrent_queue
。
我建议不要创建你自己的无锁队列,即使你听到了它的全部时尚,因为我所看到的所有首次实现都有(有时是微妙的)竞争条件。