zne*_*eak 28 c atomic volatile
我从许多来源读到这个volatile
关键字 在多线程场景中没有帮助 .但是,这个断言一直受到接受指针的原子操作函数的挑战.volatile
例如,在Mac OS X上,我们有OSAtomic
函数系列:
SInt32 OSIncrementAtomic(volatile SInt32 *address);
SInt32 OSDrecrementAtomic(volatile SInt32 *address);
SInt32 OSAddAtomic(SInt32 amount, volatile SInt32 *address);
// ...
Run Code Online (Sandbox Code Playgroud)
似乎volatile
Windows 上的关键字类似于Interlocked
操作:
LONG __cdecl InterlockedIncrement(__inout LONG volatile *Addend);
LONG __cdecl InterlockedDecrement(__inout LONG volatile *Addend);
Run Code Online (Sandbox Code Playgroud)
似乎在C++ 11中,原子类型具有volatile
修饰符的方法,它必须以某种方式表示volatile
关键字与原子性有某种关系.
那么,我错过了什么?为什么操作系统供应商和标准库设计者坚持使用volatile
关键字进行线程化,如果它没用?
Mic*_*urr 22
易失性对多线程的共享访问没有用处 - 只是它不一定足够:
此外,您还应该注意,volatile
示例中API的指针参数上的限定符实际上只是增加了API接收指向volatile
对象的指针而无需投诉的能力 - 它不需要指针指向实际volatile
对象.该标准允许非限定指针自动转换为限定指针.标准中没有提供自动转向(非限定的合格指针)(编译器通常允许它,但发出警告).
例如,如果InterlockedIncrement()
原型为:
LONG __cdecl InterlockedIncrement(__inout LONG *Addend); // not `volatile*`
Run Code Online (Sandbox Code Playgroud)
仍然可以实现API以在内部正常工作.但是,如果用户有一个他希望传递给API的易失性对象,则需要使用强制转换来防止编译器发出警告.
由于(必要或不必要),这些API通常与volatile
限定对象一起使用,将volatile
限定符添加到指针参数可防止在使用API时生成无用的诊断,并且当API与非指针一起使用时不会造成任何损害.易变物.
zne*_*eak 17
我突然想到我只是误解了它的含义volatile*
.非常类似const*
意味着指针对象不应该改变,volatile*
意味着指针对象不应该缓存在寄存器中.这是一个可以自由添加的附加约束:尽管你可以将a转换char*
为a const char*
,但你可以将其转换int*
为a volatile int*
.
因此,将volatile
修饰符应用于指针只是确保原子函数可以用于已经volatile
变量.对于非易失性变量,添加限定符是免费的.我的错误是将原型中关键字的存在解释为使用它的动机,而不是为使用它的人提供便利.