"无锁"的含义是否由C++标准定义?

Meh*_*dad 11 c++ multithreading atomic lock-free c++11

我找不到基于锁的原子与无锁原子之间的语义差异.据我所知,就语言而言,差异在语义上毫无意义,因为语言不提供任何时间保证.我能找到的唯一保证是内存排序保证,这两种情况看起来都是一样的.

(如何)原子论的无锁定能否影响程序语义?

即,除了打电话is_lock_free或者atomic_is_lock_free是有可能写出其行为实际上是受原子公司是否无锁一个明确的计划?
这些功能甚至具有语义含义吗?或者它们只是编写响应式程序的实用黑客,即使语言从未提供过时间保证?

pax*_*blo 8

至少有一个语义差异.

按照C++11 1.9 Program execution /6:

当通过接收信号中断抽象机器的处理时volatile std::sig_atomic_t,在信号处理程序的执行期间未指定既不是类型也不是无锁原子对象的对象的值,并且任何对象的值都不在任何一个中.处理程序修改的这两个类别变为未定义.

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

当然,如果你调用那样的未指定/未定义的行为,你可能会认为它不再是一个定义良好的程序,但我不完全确定你是指那个还是格式良好(即可编译).

但是,即使您忽略了语义差异,性能差异也是值得的.如果我必须有一个在线程之间进行通信的值,我可能会按优先顺序选择:

  • 无锁定的最小适当数据类型.
  • 如果数据类型是无锁的,则数据类型不是必需的,而较小的数据类型则不是.
  • 共享区域完全能够满足竞争条件,但与atomic_flag(保证无锁)一起控制访问.

可以在编译或运行时基于ATOMIC_x_LOCK_FREE宏选择此行为,以便即使程序行为相同,也选择该行为的最佳方法.


yoh*_*hjp 5

在C++ 11标准中,术语"无锁"未在LWG#2075问题中报告.

C++ 14 Standard定义了C++语言中的无锁执行(N3927批准).

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

原子函数的执行被定义为无锁(29.7)或表示为无锁(29.4)是无锁执行.

  • 如果只有一个未阻塞的线程,则该线程中的无锁执行应完成.[注意:并发执行线程可能会阻止无锁执行的进行.例如,加载锁定的存储条件实现可能会发生这种情况.这个属性有时被称为无阻碍. - 结束说明]
  • 当一个或多个无锁执行同时运行时,至少应完成一个.[注意:某些实现难以为此效果提供绝对保证,因为来自其他线程的重复且特别是不合时宜的干扰可能阻止前向进展,例如,通过在加载锁定和存储条件之间反复窃取高速缓存行以用于不相关的目的说明.实施应该确保这种影响不能无限期地延迟在预期的操作条件下的进展,因此程序员可以安全地忽略这种异常.在此国际标准之外,此酒店有时被称为无锁. - 结束说明]

"无锁"的上述定义取决于未阻塞线程的行为.C++ Standard没有直接定义未阻塞的线程,但是17.3.3 [defns.blocked]定义了被阻塞的线程:

在可以继续执行之前等待某个条件(除处理器的可用性之外)的线程


(如何)原子论的无锁定能否影响程序语义?

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