3 回答
TA贡献1820条经验 获得超2个赞
对于确定的答案,请转到规格。:)
CLI规范的第I部分,第12.6.6节指出:“符合规范的CLI必须保证对所有不超过本机字大小的正确对齐内存位置的读写访问是原子的,而对某个位置的所有写访问都相同”。
这样就可以确定s_Initialized永远不会不稳定,并且对小于32位的原始类型的读写是原子的。
特别是,double和long(Int64和UInt64)不能保证在32位平台上是原子的。您可以使用Interlocked类上的方法来保护这些方法。
另外,虽然读写是原子的,但由于必须读取,操作和重写原始类型,因此存在一种竞争条件,具有加,减,递增和递减原始类型。互锁的类使您可以使用CompareExchange和Increment方法保护它们。
互锁会形成内存屏障,以防止处理器对读取和写入进行重新排序。在此示例中,锁创建了唯一需要的屏障。
TA贡献1841条经验 获得超3个赞
徘徊-标题中的问题绝对不是Rory提出的真正问题。
名义问题的答案很简单:“否”,但是当您看到真正的问题时,这根本没有帮助。我认为没有人给出简单的答案。
罗里问的真正问题要晚得多了,并且与他所举的例子更相关。
为什么在锁之外读取s_Initialized字段?
答案也很简单,尽管与变量访问的原子性完全无关。
s_Initialized字段在锁外部读取,因为锁很昂贵。
由于s_Initialized字段本质上是“一次写入”,因此它永远不会返回假肯定。
在锁外阅读它是经济的。
这是一种低成本的具有活性高的有效益的机会。
这就是为什么要在锁之外读取它的原因-除非另有说明,否则避免支付使用锁的费用。
如果锁便宜,那么代码会更简单,并省略该第一检查。
(编辑:随后来自rory的回应很好。是的,布尔读取是非常原子的。如果有人使用非原子布尔读取构建了处理器,那么它们将在DailyWTF中使用。)
- 3 回答
- 0 关注
- 738 浏览
添加回答
举报