不是atomic<bool>多余的,因为bool它本质上是原子的吗?我认为不可能有部分修改的bool值.我什么时候真的需要用atomic<bool>而不是bool?
说到C++的并发内存模型,Stroustrup的C++编程语言,第4版,第1节.41.2.1,说:
...(像大多数现代硬件一样)机器无法加载或存储任何小于单词的东西.
但是,我的x86处理器,几年前,可以存储小于一个字的对象.例如:
#include <iostream>
int main()
{
char a = 5;
char b = 25;
a = b;
std::cout << int(a) << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果没有优化,GCC将其编译为:
[...]
movb $5, -1(%rbp) # a = 5, one byte
movb $25, -2(%rbp) # b = 25, one byte
movzbl -2(%rbp), %eax # load b, one byte, not extending the sign
movb %al, -1(%rbp) # a = b, one byte
[...]
Run Code Online (Sandbox Code Playgroud)
评论是由我提出的,但是汇编是由GCC提出的.当然,它运行良好.
显然,我不明白Stroustrup在谈到硬件可以加载和存储任何小于一个单词的内容时所说的内容.据我所知,我的计划什么也不做,但加载和存储对象小于一个字的.
C++对零成本,硬件友好的抽象的彻底关注使C++与其他易于掌握的编程语言区别开来.因此,如果Stroustrup在公交车上有一个有趣的信号心理模型,或者有其他类似的东西,那么我想了解Stroustrup的模型.
什么是 Stroustrup谈论,拜托?
更长时间的背景声明 …
注意:对于这个问题,我不是在谈论 C 或 C++语言标准。相反,我谈论的是针对特定体系结构的 gcc 编译器实现,因为语言标准对原子性的唯一保证是使用_AtomicC11 或更高版本中的类型或std::atomic<>C++11 或更高版本中的类型。另请参阅我在这个问题底部的更新。
在任何体系结构上,某些数据类型可以原子方式读取和写入,而其他数据类型则需要多个时钟周期,并且可能在操作中间被中断,如果跨线程共享该数据,则会导致损坏。
在8 位单核 AVR 微控制器(例如:Arduino Uno、Nano 或 Mini 使用的 ATmega328 mcu)上,只有8 位数据类型具有原子读取和写入(使用 gcc 编译器和gnu C 或gnu C++语言)。我在不到 2 天的时间里进行了 25 小时的马拉松式调试,然后在这里写下了这个答案。另请参阅此问题的底部以获取更多信息。以及有关使用 AVR-libc 库的 gcc 编译器编译时 AVR 8 位微控制器具有自然原子写入和自然原子读取的 8 位变量的文档。
在(32 位)STM32 单核微控制器上,任何32 位或更小的数据类型绝对自动是原子的(当使用 gcc 编译器和 gnu C 或 gnu C++ 语言编译时,因为ISO C 和 C++ 不保证这一点直到 2011 年版本,_Atomic类型为 C11 …
如何等到C++ 11线程创建后才开始?它似乎没有任何方法,不像其他一些线程库(如Qt)提供了一种特殊的方法来检查线程是否正在运行.
想象一下有两个线程,一个给一个(已经初始化的)bool赋值,另一个线程读取/检查这个bool.如果对bool的访问没有被保护或者bool是非原子的,那么线程清理程序可能会在这里检测到可能的数据竞争.
这怎么可能?是否有可能分配给bool并不总是原子的,例如,由于缓存层次结构或无序执行等硬件特性?
现在写class得很复杂,觉得我用得太多了CRITICAL_SECTION.
据我所知,某些类型的原子操作总是在没有任何硬件或软件中断的情况下执行.
我想检查一下我是否理解正确.
CRITICAL_SECTION因为这样做不会有中断.bool 是原子的.所以有我的陈述,想问一下,如果它们是正确的,如果它们是正确的,那么什么类型的变量也可以设置或没有CRITICAL_SECTION?
PS我在谈论为每种方法获取或设置一个单值,而不是两个,而不是五个,而是一个.
布尔标志由两个线程切换.以下代码是否有意义?
static bool ATOMIC_BOOL_READ( volatile bool& var )
{
return __sync_fetch_and_or(&var, 0);
}
static void ATOMIC_BOOL_WRITE(volatile bool& var, bool newval )
{
__sync_bool_compare_and_swap( &var, !newval, newval);
}
Run Code Online (Sandbox Code Playgroud)
请注意以下几点:
我正在传递一个bool引用.合理?
为了一蹴而就,我也宣称它不稳定.
更新:
我想问的基本问题是:原子性和记忆障碍之间的区别是什么?如果线程A正在变量foo上执行原子内置,则线程B不能对变量foo执行任何操作; 因此创造了一个记忆障碍?
如果 C 程序更改字节数组中的一个字节,会发生哪些机器指令?硬件是否需要读取 8 个字节、更改一个字节并存储它(使用 2 次内存操作)?
编辑:专门针对 x86-64 架构
我有一个结构数组,它是一个全局变量,其中一个结构成员是布尔值。特定 CPU 中的一个线程正在读取布尔值,不同 CPU 中的另一个线程可以通过将布尔值分配为 true 或 false ( my_array[index].bool = true/false)来定期更改布尔值。
我知道不使用任何形式的同步机制将导致未定义的行为。
但是,假设:
sizeof(bool)==1,我可以肯定地说,在上述条件下,我可以在不使用互斥锁等同步机制的情况下逃脱,并且没有未定义的行为吗?
我无法想象一个架构会在多个指令中设计对其最小数据类型的访问,但也许流水线有一些我不考虑的问题?