为什么我需要一个内存屏障? [英] Why do I need a memory barrier?

查看:169
本文介绍了为什么我需要一个内存屏障?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在果壳(强烈推荐BTW)C#4使用下列code证明内存屏障(假设A和B在不同的线程上运行)的概念:

C# 4 in a Nutshell (highly recommended btw) uses the following code to demonstrate the concept of MemoryBarrier (assuming A and B were run on different threads):

class Foo{
  int _answer;
  bool complete;
  void A(){
    _answer = 123;
    Thread.MemoryBarrier(); // Barrier 1
    _complete = true;
    Thread.MemoryBarrier(); // Barrier 2
  }
  void B(){
    Thread.MemoryBarrier(); // Barrier 3;
    if(_complete){
      Thread.MemoryBarrier(); // Barrier 4;
      Console.WriteLine(_answer);
    }
  }
}

他们提到壁垒1安培; 4 prevent从写0和障碍2和这个例子; 3提供的新鲜感的保证:他们保证,如果B A后跑了,看完 _complete 将评估为真正

they mention that Barriers 1 & 4 prevent this example from writing 0 and Barriers 2 & 3 provide a freshness guarantee: they ensure that if B ran after A, reading _complete would evaluate to true.

我真的不得到它。我想我明白为什么障碍1安培; 4是必要的:我们不想在写的 _answer 以进行优化,并放置在写后的 _complete (屏障1),我们需要确保的 _answer 是不缓存(道闸4)。我也觉得我明白了为什么屏障3是必要的:如果一个跑了,直到刚刚写入后的 _complete = TRUE ,B仍然需要刷新 _complete 以读取正确的价值

I'm not really getting it. I think I understand why Barriers 1 & 4 are necessary: we don't want the write to _answer to be optimized and placed after the write to _complete (Barrier 1) and we need to make sure that _answer is not cached (Barrier 4). I also think I understand why Barrier 3 is necessary: if A ran until just after writing _complete = true, B would still need to refresh _complete to read the right value.

我不明白,但为什么我们需要屏障2!我的一部分说,这是因为也许线程2(运行B)已经跑了,直到(但不包括)如果(_complete),所以我们需要确保的 _complete 刷新。

I don't understand though why we need Barrier 2! Part of me says that it's because perhaps Thread 2 (running B) already ran until (but not including) if(_complete) and so we need to insure that _complete is refreshed.

不过,我看不出这有助于。是不是仍然有可能, _complete 将被设置为true,A,但尚未B法会看到的缓存(假)版本的 _complete ?也就是说,如果线程2运行方式B,直到第一个内存屏障后再线程1跑去方法的,直到 _complete = TRUE ,但没有进一步的,然后线程1恢复和测试如果(_complete) - ?可能是如果不会导致的

However, I don't see how this helps. Isn't it still possible that _complete will be set to true in A but yet the B method will see a cached (false) version of _complete? Ie, if Thread 2 ran method B until after the first MemoryBarrier and then Thread 1 ran method A until _complete = true but no further, and then Thread 1 resumed and tested if(_complete) -- could that if not result in false?

推荐答案

屏障#2 guarentees该写 _complete 被立即提交。否则,它可能仍然处于排队状态的意思是 _complete B 读不会看到引起<变化code> A 即使 B 有效地使用挥发性读取。

Barrier #2 guarentees that the write to _complete gets committed immediately. Otherwise it could remain in a queued state meaning that the read of _complete in B would not see the change caused by A even though B effectively used a volatile read.

当然,这个例子并不完全公平对待的问题,因为 A 什么都不写后更 _complete 这意味着因为线程早期终止写会立即反正comitted。

Of course, this example does not quite do justice to the problem because A does nothing more after writing to _complete which means that the write will be comitted immediately anyway since the thread terminates early.

回答你的问题是否如果仍然可以评估到是肯定的确切的原因,你说明。但是,请注意笔者说,关于这一点的。

The answer to your question of whether the if could still evaluate to false is yes for exactly the reasons you stated. But, notice what the author says regarding this point.

1的障碍和4 prevent这个例子
  从写0。屏障2和3
  提供了新鲜的保证:他们
  确保如果后B A ,阅读跑
  _complete将评估为true。

Barriers 1 and 4 prevent this example from writing "0". Barriers 2 and 3 provide a freshness guarantee: they ensure that if B ran after A, reading _complete would evaluate to true.

在如果B A后跑了的重点是我的。这当然可能是因为两个线程交织的情况。但是,笔者无视这种情况下presumably使他对如何 Thread.MemoryBarrier 工作更简单一点。

The emphasis on "if B ran after A" is mine. It certainly could be the case that the two threads interleave. But, the author was ignoring this scenario presumably to make his point regarding how Thread.MemoryBarrier works simpler.

顺便说一句,我的日子不好过图谋我的机器上一个例子,其中的障碍#1和#2会改变程序的行为。这是因为对于写入内存模式是强在我的环境。也许,如果我有一个多处理器机器,是采用单声道,或有其他一些不同的设置,我可以证明它。当然,这是很容易证明,消除障碍#3,#4产生了影响。

By the way, I had a hard time contriving an example on my machine where barriers #1 and #2 would have altered the behavior of the program. This is because the memory model regarding writes was strong in my environment. Perhaps, if I had a multiprocessor machine, was using Mono, or had some other different setup I could have demonstrated it. Of course, it was easy to demonstrate that removing barriers #3 and #4 had an impact.

这篇关于为什么我需要一个内存屏障?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆