Sleep没有同步语义吗?

时间:2013-11-27 11:52:16

标签: c# clr memory-barriers

  

java规范17.3睡眠和产量

     

重要的是要注意 Thread.sleep和Thread.yield都没有任何同步语义。特别是,编译器不必在调用Thread.sleep或Thread.yield之前将寄存器中缓存的写入刷新到共享内存,编译器也不必在调用Thread.sleep或Thread后重新加载缓存在寄存器中的值。产量

     

例如,在下面(损坏的)代码片段中,假设this.done是一个非易失性布尔字段:

while (!this.done)
    Thread.sleep(1000);
     

编译器可以自由地读取this.done字段一次,并在循环的每次执行中重用缓存值。这意味着循环永远不会终止,即使另一个线程改变了this.done的值。

问题:在C#中是否相同?

我们知道,我们可以添加Thread.MemoryBarrier();解决问题。

while(this.done)
{
    Thread.MemoryBarrier();
    Thread.sleep(1000);
}

问题:但是在下列情况下编译器是否能够将fun()识别为MemoryBarrier?

public static void fun()
{
    Thread.MemoryBarrier();
}
while(this.done)
{
    fun();
    Thread.sleep(1000);
}

如果没问题,为什么它不能将睡眠识别为MemoryBarrier,因为它无法确定睡眠是否包含MemoryBarrier?

1 个答案:

答案 0 :(得分:1)

由于Sleep没有明确声称拥有任何此类语义,唯一安全的答案是“不要依赖它具有任何此类语义”#34;。有很多方法可以安全地轮询变量或检查其他一些令牌(我个人很想看Monitor.Wait(obj, timeout),但YMMV)。你说:

  

我认为睡眠和其他功能应该被识别为MemoryBarrier。

由于Sleep方法并未声明要执行此操作,因此您无法依赖它。可能是设计师积极地反对你;可能它甚至从未进行过讨论(毕竟,这是一种相当随意的效果)。