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

发布于 2024-12-02 11:29:07 字数 701 浏览 1 评论 0原文

由于看起来上下文切换可能发生在指令执行的任何时候,我现在想知道为什么代码“部分有问题”(这两条指令)有意义,如果上下文切换可以在任何指令之间发生并且我们可能在不同的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。

(这与这个问题相关)

Since it appears that context switch may happen at any point in execution of instructions I am now wondering why code "in part in question" (those 2 instructions) makes sense, if context switch can happen between any instructions and we may be on different CPU core in second instruction.

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

Description on MemoryBarrier here doesn't appear to give guarantees MemoryBarrier that CPUs won't be switched after calling it.

(this is related to this question)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

原来分手还会想你 2024-12-09 11:29:07

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

There are no guarantees that a context switch will or won't happen around a MemoryBarrier. These are orthogonal concepts.

时光病人 2024-12-09 11:29:07

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

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

至于您的另一个问题,为什么需要屏障 4:

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

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

  Console.WriteLine (tmpanswer);
}

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

但请记住,代码示例仅为 void B() 中的代码提供了这一保证(前提是 A() 仅运行一次

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

因此,除非A 和 B 串行运行,代码不提供任何锁定/通知,以便 B 始终打印 123。 A() 和 B() 可以在执行过程中的任何时候交错/中断 - 您无法控制谁可以访问运行时。

无论您以哪种顺序启动 2 个线程,都不能保证 B() 在 A() 之后运行。(尽管在代码中的其他地方,您可以先启动 A() 并在启动 B 之前显式等待它完成() 当然)

What guarantees that context-switch will not happen after Thread.MemorryBarrier() call?

Nothing. MemoryBarriers does not prevent context switching, (or atomic execution of your code).

As to your other question, why Barrier 4 is needed:

In the example code from the previous question, the C# compiler, CLR or the CPU might reorder reading of the answer variable before the completed variable if barrier 4 was not there. i.e. the code that actually runs could be similar to:

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

  Console.WriteLine (tmpanswer);
}

A barrier before the Console.WriteLine() will prevent reading _answer before reading _completed

But keep in mind that the code example only provides this one guarantee about the code in void B() (provided A() is run only once )

  • If the _complete variable is true , then Console.WriteLine will write out 123 and not 0.

So, unless A and B are run serially, the code does not provide any locking/notification such that B will always print 123. A() and B() could be interleaved/interrupted any time in its execution - you have no control over who gets to run when.

There is no guarantee that B() runs after A(), no matter which order you started the 2 threads in. (Though somewhere else in the code , you could start A() first and wait explicitly for it to finish before starting B() ofcourse)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文