参考分配和阅读原子操作?

时间:2011-04-28 10:08:16

标签: c# .net multithreading visual-studio-2010

我发现了关于同一主题的几个问题,但与一般变量(值和引用类型)有关 this question接受的回答是:

CLI规范第12.6.6节的分区I指出:“符合要求的CLI应保证在对位置的所有写入访问都是对原始字大小不大时,对正确对齐的内存位置的读写访问权限是原子的。大小相同。“

引用变量(即类)是指针,等于本机字大小,但我有几个疑问:

是否保证引用位于正确对齐的内存位置?

我不明白最后一部分。这是什么意思? “...当对一个位置的所有写访问都是相同的大小时。”

简而言之,obj2保证在以下代码的循环的每次迭代中都有效吗?

class MyClass
{
    private OtherClass m_Object;

    void Thread1()
    {
        while(true)
        {
            OtherClass obj1 = new OtherClass();
            m_Object = obj1;
        }
    }

    void Thread2()
    {
        while (true)
        {
            OtherClass obj2 = m_Object;
            // Is obj2 guaranteed to be valid?
            obj2.Check();
        }
    }
}

1 个答案:

答案 0 :(得分:11)

是的,保证一切都正确对齐,除非你故意不采取措辞错位,这意味着参考分配/读取保证是原子的。

CLI规范的第12.6.6节继续这样说:

  

除非明确的布局控制(参见   分区II(控制实例   Layout))用于更改默认值   行为,数据元素不大于   自然字大小(a。的大小   native int)应该是正确的   对齐。对象引用应为   对待它们就好像存放在   原生单词大小。

在规范第12.6.2节中还有关于对齐等的更多细节。

请注意,在您的示例代码中,读取线程2保证是原子的,但保证实际看到线程1所做的任何更改:不强制执行内存障碍或每个线程的波动性可以使用自己的m_Object字段的“视图”,而不会看到其他线程所做的更改。

因此,例如,线程1可以将(原子)写入其自己的m_Object视图中,但数据实际上只保存在寄存器或CPU缓存中,并且从未进入主存储器。类似地,线程2也可以进行m_Object的(原子)读取,但实际上是从寄存器或CPU缓存而不是主存储器中读取。