C#:使用具有联锁的易失性字段

C#:使用具有联锁的易失性字段,c#,multithreading,volatile,memory-barriers,C#,Multithreading,Volatile,Memory Barriers,我的理解是.NET中所有的互锁的API都将引入一个完整的内存围栏。然而,我仍然看到许多示例,其中引入了半围栏的volatile与Interlocked一起使用。例如Task.Id: private volatile int m_taskId; 公共整数Id { 得到 { 如果(m_taskId==0) { int newId=newId(); 联锁。比较交换(参考m_任务ID,新ID,0); } 返回m_taskId; } } 在这种情况下,volatile实际在做什么?volatile在这

我的理解是.NET中所有的
互锁的
API都将引入一个完整的内存围栏。然而,我仍然看到许多示例,其中引入了半围栏的
volatile
Interlocked
一起使用。例如
Task.Id

private volatile int m_taskId;
公共整数Id
{
得到
{
如果(m_taskId==0)
{
int newId=newId();
联锁。比较交换(参考m_任务ID,新ID,0);
}
返回m_taskId;
}
}

在这种情况下,
volatile
实际在做什么?

volatile
在这种特殊情况下似乎没有做任何事情。volatile做了两件事:它确保编译器不会进行会干扰变量正确使用的优化;而且,在某些平台上,它将确保在一个线程中设置的值在另一个线程中可见。请注意,“英特尔x86/x64”体系结构隐式地实现了后一个目标,但并非所有其他平台都是如此。@PeterDuniho这是有道理的,但互锁操作是否也能确保这两个目标?或者这是特定于
volatile
关键字和
volatile
API的吗?“联锁操作不也确保这两件事吗?”--不。联锁操作影响代码中实际执行联锁操作的站点。编译器无法知道在优化使用变量的代码时,该变量是否已在其他地方调用
Interlocked
方法时使用。类似地,一个线程中的内存限制只影响该线程中读取和/或写入操作的重新排序;你需要另一个铁丝网来做同样的事情,否则,操作仍然会以一种有问题的方式重新排序。
volatile
在这种特殊情况下似乎不会做任何事情。volatile做了两件事:它确保编译器不会进行会干扰变量正确使用的优化;而且,在某些平台上,它将确保在一个线程中设置的值在另一个线程中可见。请注意,“英特尔x86/x64”体系结构隐式地实现了后一个目标,但并非所有其他平台都是如此。@PeterDuniho这是有道理的,但互锁操作是否也能确保这两个目标?或者这是特定于
volatile
关键字和
volatile
API的吗?“联锁操作不也确保这两件事吗?”--不。联锁操作影响代码中实际执行联锁操作的站点。编译器无法知道在优化使用变量的代码时,该变量是否已在其他地方调用
Interlocked
方法时使用。类似地,一个线程中的内存限制只影响该线程中读取和/或写入操作的重新排序;您需要在其他线程中设置另一个围栏来执行相同的操作,否则操作仍然会以有问题的方式重新排序。