【问题标题】:should I synchronize the deque or not我应该同步双端队列吗
【发布时间】:2013-08-17 15:06:30
【问题描述】:

我在 C++ 应用程序中有一个带有指针的 deque。我知道有 两个线程 可以访问它。

Thread1 将从后面添加指针,Thread2 将从前面处理和删除指针。

Thread2 会等到deque 达到一定数量,说是10 个项目,然后开始处理它。它一次只会循环和处理 10 个项目。与此同时,Thread1 可能仍会继续向双端队列添加新项目。

我认为不同步deque 会很好,因为Thread1Thread2 正在访问deque 的不同部分。它是deque 而不是vector。因此,container 的现有内存不会被重新分配。

我说的对吗?如果不是,为什么(我想知道我错过了什么)?

编辑:

我知道始终同步它不会有什么坏处。但这可能会损害性能或没有必要。如果可能的话,我只是希望它运行得更快、更正确。

【问题讨论】:

  • 我猜你应该总是在有疑问时使用同步。
  • 是的,你应该同步。
  • 听起来你想要一个无锁队列,而不是 std::deque。
  • @bash.d - 如果有疑问,请不要编写代码;解开疑惑。

标签: c++ c multithreading 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 至少可以同时被入队和出队操作访问(尤其是当数组变得太小并且需要复制到更大的数组中时)。


那么,有什么选择呢?您正在寻找的是并发队列。那里有一些实现,你可能不应该太担心它们是否是无锁的,除非它被证明是一个瓶颈。一个例子是TTB concurrent_queue

我建议不要创建自己的无锁队列,即使你听说这只是一种时尚,因为我看到的所有第一个实现都有(有时是微妙的)竞争条件。

【讨论】:

    猜你喜欢
    • 2015-02-16
    • 2018-07-02
    • 1970-01-01
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 2017-01-14
    • 2011-05-21
    • 2018-05-09
    相关资源
    最近更新 更多