"lock-free" 的含义是否由 C++ 标准定义?

Is the meaning of "lock-free" even defined by the C++ standard?

我找不到基于锁和无锁原子之间的语义差异。据我所知,就语言而言,差异在语义上没有意义,因为该语言不提供任何时间保证。我能找到的唯一保证是内存排序保证,这两种情况似乎都是一样的。

(如何)原子的无锁性会影响程序语义?

也就是说,除了调用 is_lock_freeatomic_is_lock_free 之外,是否有可能编写一个定义明确的程序,其行为实际上受到原子是否无锁的影响?
这些功能甚至具有语义意义吗?或者它们只是用于编写响应式程序的实用技巧,即使该语言从一开始就没有提供时间保证?

至少有一个语义差异。

根据C++11 1.9 Program execution /6

When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects which are neither of type volatile std::sig_atomic_t nor lock-free atomic objects are unspecified during the execution of the signal handler, and the value of any object not in either of these two categories that is modified by the handler becomes undefined.

换句话说,处理这两类变量是安全的,但应避免对所有其他类别的任何访问或修改。

当然,如果您调用 unspecified/undefined 那样的行为,您可能会争辩说它不再是一个很好的 定义的 程序,但我不完全确定您是不是这个意思或格式正确(即可编译)。

但是,即使您不考虑语义差异,性能 差异也值得拥有。如果我必须有一个线程间通信的值,我可能会按优先顺序选择:

  • 最小的无锁数据类型。
  • 一个比必要的更大的数据类型,如果它是无锁的而较小的则不是。
  • 一个完全有竞争条件的共享区域,但与 atomic_flag(保证无锁)一起控制访问。

可以根据 ATOMIC_x_LOCK_FREE 宏在编译或 运行 时选择此行为,这样即使程序的行为无论如何都相同,最佳的 方法 因为选择了该行为。

Paxdiablo 回答得很好,但一些背景知识可能会有所帮助。

"Lock-free atomic" 是一些多余的术语。正如最初发明的那样,原子变量的要点是通过利用硬件保证来避免锁定。但是,每个平台都有其自身的局限性,而 C++ 具有很高的可移植性。因此,实现必须使用细粒度锁模拟原子性(通常通过库),这些原子类型在硬件级别并不存在。

硬件原子和 "software atomics," 之间的行为差​​异已最小化,因为差异意味着失去可移植性。另一方面,程序应该能够避免意外使用互斥量,因此可以通过预处理器可用的 ATOMIC_x_LOCK_FREE 进行内省。

在 C++11 标准中,术语 "lock-free" 未如 issue LWG #2075 中所报告的那样得到很好的定义。

C++14 标准定义了 C++ 语言中的无锁执行N3927 已批准)。

引用 C++14 1.10[intro.multithread]/第 4 段:

Executions of atomic functions that are either defined to be lock-free (29.7) or indicated as lock-free (29.4) are lock-free executions.

  • If there is only one unblocked thread, a lock-free execution in that thread shall complete. [ Note: Concurrently executing threads may prevent progress of a lock-free execution. For example, this situation can occur with load-locked store-conditional implementations. This property is sometimes termed obstruction-free. -- end note ]
  • When one or more lock-free executions run concurrently, at least one should complete. [ Note: It is difficult for some implementations to provide absolute guarantees to this effect, since repeated and particularly inopportune interference from other threads may prevent forward progress, e.g., by repeatedly stealing a cache line for unrelated purposes between load-locked and store-conditional instructions. Implementations should ensure that such effects cannot indefinitely delay progress under expected operating conditions, and that such anomalies can therefore safely be ignored by programmers. Outside this International Standard, this property is sometimes termed lock-free. -- end note ]

以上 "lock-free" 的定义取决于未阻塞线程的行为。 C++标准没有直接定义unblocked thread,但是17.3.3[defns.blocked]定义了blocked thread:

a thread that is waiting for some condition (other than the availability of a processor) to be satisfied before it can continue execution


(How) can the lock-free-ness of atomics affect program semantics?

我认为答案是否定的,除了信号处理程序 ,当 "program semantics" 意味着原子操作的副作用。 原子的无锁性影响整个多线程程序的进度保证强度。 当两个(或多个)线程同时对同一对象执行无锁原子操作时,这些操作中至少有一个应该在 any 最差线程调度下完成。 换句话说,'evil' 线程调度程序理论上可以故意阻止基于锁的原子操作的进程。