tbb::concurrent_bounded_queue::size 线程不安全吗?

问题描述

来源有以下评论

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

但后来我查看了内部实现,这一切似乎都是线程安全的(操作是 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;
}

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

解决方法

它是线程安全的,因为 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 的原始架构师,但不再为 Intel 工作,所以我不能代表当前版本的意图。)

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...