C++ 是“的意思;“无锁”;甚至由C++;标准
我找不到基于锁和无锁原子之间的语义差异。就我所知,就语言而言,这种差异在语义上毫无意义,因为语言不提供任何时间保证。我能找到的唯一保证是内存顺序保证,这两种情况似乎都是一样的 原子的无锁性如何影响程序语义? i、 例如,除了调用C++ 是“的意思;“无锁”;甚至由C++;标准,c++,multithreading,c++11,atomic,lock-free,C++,Multithreading,C++11,Atomic,Lock Free,我找不到基于锁和无锁原子之间的语义差异。就我所知,就语言而言,这种差异在语义上毫无意义,因为语言不提供任何时间保证。我能找到的唯一保证是内存顺序保证,这两种情况似乎都是一样的 原子的无锁性如何影响程序语义? i、 例如,除了调用is_lock_free或atomic_is_lock_free,是否可以编写一个定义良好的程序,其行为实际上受原子是否无锁的影响? 这些函数甚至有语义意义吗?或者,它们只是编写响应性程序的实用技巧,即使该语言从一开始就不提供时间保证?至少有一个语义差异 根据C++11
is_lock_free
或atomic_is_lock_free
,是否可以编写一个定义良好的程序,其行为实际上受原子是否无锁的影响?这些函数甚至有语义意义吗?或者,它们只是编写响应性程序的实用技巧,即使该语言从一开始就不提供时间保证?至少有一个语义差异 根据
C++11 1.9程序执行/6
:
当接收到信号而中断抽象机器的处理时,在执行信号处理程序期间,不属于类型volatile std::sig_atomic_t
或无锁原子对象的对象的值将被指定,并且任何对象的值都不在以下任何一种类型中:
处理程序修改的这两个类别将变得未定义
换言之,这两类变量是安全的,但应避免对所有其他类别的访问或修改
当然,如果您调用未指定/未定义的行为,您可能会争辩说它不再是一个定义良好的程序,但我不完全确定您的意思是这样的还是格式良好(即可编译的)
但是,即使你忽略了语义上的差异,性能上的差异也是值得的。如果我必须要有一个线程间通信的值,我可能会按照优先顺序选择:
- 无锁的最小适当数据类型
- 如果数据类型没有锁,而较小的数据类型没有锁,则数据类型比需要的大
- 一个完全能够满足竞争条件的共享区域,但与
(保证无锁)一起控制访问原子_标志
这种行为可以在编译或运行时基于
ATOMIC_x_LOCK_FREE
宏选择,这样,即使程序的行为相同,也会选择这种行为的最佳方法。Paxdiablo回答得很好,但一些背景知识可能会有所帮助
“无锁原子”是一个多余的术语。原子变量最初被发明出来的目的是通过利用硬件保证来避免锁。但是,每个平台都有其自身的局限性,C++是高度可移植的。因此,实现必须使用细粒度锁来模拟原子性(通常通过库),这些锁用于在硬件级别并不存在的原子类型
硬件原子和“软件原子”之间的行为差异被最小化,因为差异将意味着失去可移植性。另一方面,一个程序应该能够避免意外使用互斥锁,因此通过预处理器可用的
原子锁自由
进行内省。在C++11标准中,术语“无锁”的定义不如中所述
C++ 14标准定义了C++中的无锁执行(批准)。 引用C++14 1.10[简介.多线程]/第4段:
定义为无锁(29.7)或指示为无锁(29.4)的原子函数的执行是无锁执行- 如果只有一个未阻塞线程,则该线程中的无锁执行应完成。[注意:并发执行线程可能会阻止无锁执行的进程。例如,加载锁定存储条件实现可能会出现这种情况。此属性有时称为无障碍。--结束注意]
- 当一个或多个无锁执行同时运行时,至少应完成一个。[注意:某些实现很难对此提供绝对保证,因为来自其他线程的重复且特别不合时宜的干扰可能会阻止向前的进程,例如,通过在加载锁定和存储条件指令之间为不相关的目的重复窃取缓存线。实现应在预期操作条件下,此类影响不能无限期地延迟进度,因此程序员可以安全地忽略此类异常。在本国际标准之外,此属性有时被称为无锁。--尾注]
原子的无锁性如何影响程序语义 我认为答案是否定的,除了信号处理器as,当“程序语义”意味着原子操作的副作用时。 原子的无锁性影响整个多线程程序的进程保证强度。 当两个(或多个)线程同时对同一对象执行无锁原子操作时,在任何最差的线程调度下,至少应完成其中一个操作。 换句话说,“邪恶”线程调度器可以有意地阻止基于锁的原子操作的进展。从我理解的情况来看,(免责声明:我没有C++做过很多年,但是从好奇的角度看了文档),不同之处在于,访问一个无锁对象的线程永远不会被阻塞。而基于锁的对象可能会导致线程