我发现了关于同一主题的几个问题,但与一般变量(值和引用类型)有关 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();
}
}
}
答案 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缓存而不是主存储器中读取。