假设:
A. WIN32下的C++.
B.正确对齐的易失性整数使用InterlockedIncrement()和递增和递减InterlockedDecrement().
__declspec (align(8)) volatile LONG _ServerState = 0;
Run Code Online (Sandbox Code Playgroud)
如果我想简单地读取_ServerState,我是否需要通过InterlockedXXX函数读取变量?
例如,我见过如下代码:
LONG x = InterlockedExchange(&_ServerState, _ServerState);
Run Code Online (Sandbox Code Playgroud)
和
LONG x = InterlockedCompareExchange(&_ServerState, _ServerState, _ServerState);
Run Code Online (Sandbox Code Playgroud)
目标是简单地读取当前的值_ServerState.
我不能简单地说:
if (_ServerState == some value)
{
// blah blah blah
}
Run Code Online (Sandbox Code Playgroud)
这个问题似乎有些混乱.我理解在Windows中注册大小的读取是原子的,所以我认为这个InterlockedXXX函数是不必要的.
马特J.
好的,谢谢你的回复.顺便说一句,这是Visual C++ 2005和2008.
如果这是真的,我应该使用一个InterlockedXXX函数来读取它的值_ServerState,即使只是为了清楚起见,最好的方法是什么?
LONG x = InterlockedExchange(&_ServerState, _ServerState);
Run Code Online (Sandbox Code Playgroud)
这具有修改值的副作用,当我真正想做的就是阅读它.不仅如此,如果存在上下文切换,我可以将标志重置为错误的值,因为_ServerState在准备调用时将值推到堆栈上InterlockedExchange().
LONG x = InterlockedCompareExchange(&_ServerState, _ServerState, _ServerState);
Run Code Online (Sandbox Code Playgroud)
我从我在MSDN上看到的一个例子中得到了这个.
见http://msdn.microsoft.com/en-us/library/ms686355(VS.85).aspx
我所需要的只是一条线:
lock mov …Run Code Online (Sandbox Code Playgroud) 注意:对于这个问题,我不是在谈论 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 …