首先,我们有InterlockedExchange64();
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683593%28v=vs.85%29.aspx
LONGLONG __cdecl InterlockedExchange64( __inout LONGLONG volatile *Target, __in LONGLONG Value );
其次,我们有编译器内在的,_InterlockedExchange64(),注意没有volatile;
http://msdn.microsoft.com/en-us/library/1s26w950%28v=vs.80%29.aspx
__int64 _InterlockedExchange64( __int64 * Target, __int64 Value );
接下来,我们有InterlockedExchangePointer(),它与InterlockedExchange64()类似,使用volatile。
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683609%28v=vs.85%29.aspx
PVOID __cdecl InterlockedExchangePointer( __inout PVOID volatile *Target, __in PVOID Value );
但现在我们来到指针交换的内在函数,_InterlockedExchangePointer(),在这里我们看到volatile使用了!
http://msdn.microsoft.com/en-us/library/853x471w.aspx
void * _InterlockedExchangePointer( void * volatile * Target, void * Value );
基础指令在所有情况下都是相同的,那么是什么给出了?文档错误?
GCC的instrincs并没有提到交易所的波动,但他们也没有提到它的CAS!所以这没有帮助。
我的观点是CAS目标是不稳定的,因为您只能在运行时知道交换是否会发生;但原子交换不应该是易失性的,因为目标总是更新的(即使它的值没有改变),所以编译器没有不确定性。
我也看到InterlockedIncrement()的函数是易失性的,但instrincs不是。 CAS的内在函数对其目的地来说是不稳定的。
答案 0 :(得分:3)
__readfsdword
仅在VS 2005文档下标记为内核),您应该注意的是编译器使用的定义,在本例中, intrin.h
中的定义(取自VS2010 Ultimate SP1):
__MACHINEI(long _InterlockedExchange(long volatile *, long))
__MACHINEIA64(__int64 _InterlockedExchange64(__int64 volatile *, __int64))
我们可以看到它们确实是volatile
指针所必需的。
最后要注意的是,您的所有链接都是VS 2005文档(默认情况下由谷歌链接到较旧的内在函数),因此请确保使用页面顶部的下拉菜单切换到最新版本。< / p>
答案 1 :(得分:1)
这些函数不是指向volatile的指针 ,它是允许的。也就是说,如果参数声明为long *而不是long volatile *,则传递volatile变量的地址会产生此错误:
cannot convert argument 1 from 'volatile LONGLONG *' to 'LONGLONG *'
这可以通过这个简单的代码看出:
LONGLONG a;
volatile LONGLONG b;
void DoSomething(LONGLONG* p) {}
int main() {
DoSomething(&a);
DoSomething(&c); // Error!
return 0;
}
在C / C ++中,滥用volatile作为一种表明变量可能被其他线程修改的方式有着悠久的传统。这是错误的,因为volatile实际上并没有为多线程提供有意义的有用语义,但是当C ++没有承认多线程开发人员变得绝望时。使用volatile的问题在于它不会阻止编译器或CPU重新排序,因此它在多线程代码中有99%的时间是错误的。
缺少C ++ 11安全的做法是只使用Interlocked *函数引用这些线程共享变量。如果你这样做,那么不需要volatile。或者,像一个理智的人一样使用锁。
但是,由于许多开发人员用原子标记他们的线程共享变量,因此Interlocked *函数必须接受这些变量。这就是为什么他们都采用指向易失性的类型。