试图理解Thread.MemoryBarrier()和上下文切换之间的关系

时间:2011-08-31 17:09:27

标签: c# .net multithreading context-switch memory-barriers

由于看起来上下文切换可能发生在执行指令的任何时刻,我现在想知道为什么代码“部分有问题”(那2条指令)是有意义的,如果上下文切换可能发生在任何指令之间我们可能是在第二条指令中的不同CPU核心上。

void B()
  {
    Thread.MemoryBarrier();    // Barrier 3
    if (_complete)
    {
      //PART IN QUESTION
      Thread.MemoryBarrier();       // Barrier 4
      Console.WriteLine (_answer);
      //END PART IN QUESTION
    }
  }

MemoryBarrier的描述似乎没有保证MemoryBarrier在调用CPU后不会切换它。

(这与此question相关)

2 个答案:

答案 0 :(得分:3)

无法保证在MemoryBarrier周围发生或不会发生上下文切换。这些是正交概念。

答案 1 :(得分:2)

  

什么保证在Thread.MemorryBarrier()调用后不会发生上下文切换?

无。 MemoryBarriers不会阻止上下文切换(或代码的原子执行)。

关于你的另一个问题,为什么需要障碍4:

在上一个问题的示例代码中,如果屏障4不存在,则C#编译器,CLR或CPU可能会在完成的变量之前重新排序应答变量的读取。即实际运行的代码可能类似于:

Thread.MemoryBarrier();    // Barrier 3
int tmpanswer = _answer;
if (_complete)
{

  Console.WriteLine (tmpanswer);
}

Console.WriteLine()之前的屏障会在阅读_answer之前阻止阅读_completed

但请记住,代码示例仅提供有关void B()中代码的一个保证(假设A()仅运行一次

  • 如果_complete变量为true,则Console.WriteLine将写出123而不是0。

因此,除非A和B是串行运行的,否则代码不会提供任何锁定/通知,因此B将始终打印123. A()和B()可以在执行时随时交错/中断 - 你有无法控制谁在何时运行。

不能保证B()在A()之后运行,无论你在哪个顺序启动2个线程。(虽然代码中的其他地方,你可以先启动A()并明确等待它完成在开始B()之前)