tbb::concurrent_bounded_queue::size 线程不安全吗?
Is tbb::concurrent_bounded_queue::size thread unsafe?
来源有以下评论:
// 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的原始架构师,但不再为英特尔工作,所以我不能代表当前版本的意图。)
当队列处于静止状态时,returned 值是准确的,而不是静止状态时可能不准确。实际上,实现 size()
到 return 原子快照不会增加太多价值,因为如果队列处于活动状态,returned 值可能会立即变得不准确。这就是为什么有 try_push
和 try_pop
之类的操作,而不是像在常规 STL 中那样让用户检查队列,然后作为单独的操作对其进行操作。
来源有以下评论:
// 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的原始架构师,但不再为英特尔工作,所以我不能代表当前版本的意图。)
当队列处于静止状态时,returned 值是准确的,而不是静止状态时可能不准确。实际上,实现 size()
到 return 原子快照不会增加太多价值,因为如果队列处于活动状态,returned 值可能会立即变得不准确。这就是为什么有 try_push
和 try_pop
之类的操作,而不是像在常规 STL 中那样让用户检查队列,然后作为单独的操作对其进行操作。