【问题标题】:Is tbb::concurrent_bounded_queue::size thread unsafe?tbb::concurrent_bounded_queue::size 线程不安全吗?
【发布时间】:2021-07-16 14:14:28
【问题描述】:

来源有以下评论:

// Return the number of items in the queue; thread unsafe
std::ptrdiff_t size() const {
    return my_queue_representation->size();
}

但后来我查看了内部 impl,这一切似乎都是线程安全的(操作是 std::atomic 的负载,然后是一些减法)。

std::ptrdiff_t size() const {
    __TBB_ASSERT(sizeof(std::ptrdiff_t) <= sizeof(size_type), NULL);
    std::ptrdiff_t hc = head_counter.load(std::memory_order_acquire);
    std::ptrdiff_t tc = tail_counter.load(std::memory_order_relaxed);
    std::ptrdiff_t nie = n_invalid_entries.load(std::memory_order_relaxed);

    return tc - hc - nie;
}

评论是错误的,还是我遗漏了什么?

【问题讨论】:

  • 我看不出它是如何实现线程安全的。加载了 3 个单独的原子,并且值可以在两者之间变化。迟早你会得到一个负尺寸返回。

标签: c++ multithreading thread-safety tbb


【解决方案1】:

它是线程安全的,因为行为由 C++ 标准明确定义,即没有标准中定义的竞争条件。从结果是队列的原子快照的意义上说,它不是线程安全的,即不是顺序一致的实现。

允许负尺寸是经过深思熟虑的设计决定。 N 的负数表示有 N 个待处理的弹出。旧版本的 TBB 有这样的评论:

//! Integral type for representing size of the queue.
/** Note that the size_type is a signed integral type.
    This is because the size can be negative if there are pending pops without corresponding pushes. */
typedef std::ptrdiff_t size_type;

最新版本似乎缺少注释。 (我是 TBB 的原始架构师,但不再为英特尔工作,所以我不能代表当前版本的意图。)

队列静止时,返回值准确,非静止时返回值可能不准确。实际上,实现size() 以返回原子快照不会增加太多价值,因为如果队列处于活动状态,则返回的值可能会立即变得不准确。这就是为什么会有 try_pushtry_pop 之类的操作,而不是像在常规 STL 中那样让用户检查队列,然后将其作为单独的操作进行操作。

【讨论】:

  • 当前 tbb 源评论是垃圾......他们甚至没有更新文档以反映 pop 现在与 try_pop 具有相同的签名
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 2020-04-15
  • 1970-01-01
  • 2011-07-04
  • 2014-04-26
  • 2012-11-30
相关资源
最近更新 更多