这个问题是评论的后续this https://stackoverflow.com/questions/40979715/do-semaphores-prevent-instruction-reordering thread.
假设我们有以下代码:
// (1)
lock (padlock)
{
// (2)
}
var value = nonVolatileField; // (3)
此外,我们假设没有指令(2)
有任何影响nonVolatileField
反之亦然。
可以读指令吗(3)
以这样的方式重新排序,使其在 lock 语句之前结束(1)
或者在里面(2)
?
据我所知,C# 规范 (§3.10) 和 CLI 规范 (§I.12.6.5) 中没有任何内容禁止此类重新排序。
请注意,这不是同一个问题this https://stackoverflow.com/questions/5996267/c-sharp-enforcing-order-of-statement-execution一。在这里我特别询问有关读取指令的问题,因为据我了解,它们不被视为副作用并且保证较弱。
I believeCLI 规范部分保证了这一点,尽管它并不那么明确。从 I.12.6.5 开始:
获取锁(System.Threading.Monitor.Enter
或进入同步方法)应隐式执行易失性读取操作,并释放锁
(System.Threading.Monitor.Exit
或离开同步方法)应隐式执行易失性写入操作。参见§I.12.6.7。
然后从 I.12.6.7 开始:
易失性读取具有“获取语义”,这意味着读取保证发生在 CIL 指令序列中读取指令之后发生的任何对内存的引用之前。易失性写入具有“释放语义”,这意味着写入保证发生在 CIL 指令序列中写入指令之前的任何内存引用之后。
因此进入锁应该阻止(3)移动到(1)。读自nonVolatileField
我相信仍然算作“对记忆的参考”。然而,当锁退出时,读取仍然可以在易失性写入之前执行,因此仍然可以将其移至(2)。
目前,C#/CLI 内存模型还有很多不足之处。我希望整个事情能够得到显着澄清(并且可能会收紧,以使一些“理论上有效但实际上很糟糕”的优化无效)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)