半 - 围栏和全栅栏?围栏、栅栏

2023-09-02 21:36:28 作者:孤独成病

(此线程的东西让我headeche)的

香港专业教育学院一直在读全部围栏 prevents周围围栏(通过memoryBarrier)重新排序或缓存任何指令

ive been reading that Full fences prevents any kind of instruction reordering or caching around that fence ( via memoryBarrier)

然后我读挥发性产生半篱笆:

volatile关键字指示编译器生成   收购围栏上的那场每次读取,和释放栅栏上   每次写入该字段。

The volatile keyword instructs the compiler to generate an acquire-fence on every read from that field, and a release-fence on every write to that field.

有我的问题:

收购围栏

这是获取围栏prevents其它读取/从之前移动写入   篱笆;

An acquire-fence prevents other reads/writes from being moved before the fence;

释放栅栏

一个释放栅栏prevents其它读取/从后移动写道:   围墙。

【大庆新款玻璃钢草坪围栏 玻璃钢化工护栏 全系列全规格】- 黄页88网

A release-fence prevents other reads/writes from being moved after the fence.

有人可以解释我这2句简单英语?

can someone please explain me these 2 sentences in simple English ?

(在哪里围栏?在memoryBarrier我把我的地方......想围栏)的

一些答案​​这里经过 - 我犯了一个平局,可以帮助大家 - 我觉得

after some answers here - i made a draw which can help everyone - i think.

http://i.stack.imgur.com/A5F7P.jpg

http://i.stack.imgur.com/A5F7P.jpg

推荐答案

你指的样子了,我经常使用的措辞。该规范说,这虽然:

The wording you refer to looks like that which I often use. The specification says this though:

volatile字段的读取被称为挥发性读取。挥发性读了收购语义;也就是说,它是保证之前到存储器之后它发生在指令序列中的任何引用发生。 volatile字段的写称为性写。挥发性写有释放语义;也就是说,它是保证发生后前在指令序列中的写指令的任何内存引用。

不过,我通常使用你提问中提到的字眼,因为我希望把重点放在事实说明的可以移动的。你所引用的文字和说明书是等效的。

But, I usually use the wording you cited in your question because I want to put the focus on the fact that instructions can be moved. The wording you cited and the specification are equivalent.

我要present几个例子。在这些例子中,我将使用一个使用↑箭头指示释放栅栏和↓箭头一个特殊的符号来表示某个acquire栅栏。没有其他的指令允许向下浮动过去的↑箭头或向上过去一个↓箭头。想想箭头的从它击退了所有一切。

I am going to present several examples. In these examples I am going to use a special notation that uses an ↑ arrow to indicate a release-fence and a ↓ arrow to indicate an acquire-fence. No other instruction is allowed to float down past an ↑ arrow or up past an ↓ arrow. Think of the arrow head as repelling everything away from it.

考虑以下code。

static int x = 0;
static int y = 0;

static void Main()
{
  x++
  y++;
}

重写它显示了各个指令是这样的。

Rewriting it to show the individual instructions would look like this.

static void Main()
{
  read x into register1
  increment register1
  write register1 into x
  read y into register1
  increment register1
  write register1 into y
}

现在,因为有在这个例子中没有存储器屏障C#编译器,JIT编译器,或硬件可以被用于优化它以许多不同方式的只要能够感觉到的执行的线程的逻辑顺序是一致物理序列的。这里是一个这样的优化。请注意如何读取和写入/从 X 得到了交换。

Now, because there are no memory barriers in this example the C# compiler, JIT compiler, or hardware is free to optimize it in many different ways as long as the logical sequence as perceived by the executing thread is consistent with the physical sequence. Here is one such optimization. Notice how the reads and writes to/from x and y got swapped.

static void Main()
{
  read y into register1
  read x into register2
  increment register1
  increment register2
  write register1 into y
  write register2 into x
}

现在这个时间会改变这些变量挥发性。我会用我们的箭头符号来标记内存屏障。请注意的顺序读取和写入/从 X 是preserved。这是因为指令不能搬过去我们的障碍(表示以↓和↑键箭头头)。现在,这是很重要的。公告称,增量,写X 的说明仍然允许向下浮动和的读取漂浮起来。这仍然是有效的,因为我们使用的半围墙。

Now this time will change those variables to volatile. I will use our arrow notation to mark the memory barriers. Notice how the order of the reads and writes to/from x and y are preserved. This is because instructions cannot move past our barriers (denoted by the ↓ and ↑ arrow heads). Now, this is important. Notice that the increment and write of x instructions were still allowed to float down and the read of y floated up. This is still valid because we were using half fences.

static volatile int x = 0;
static volatile int y = 0;

static void Main()
{
  read x into register1
  ↓    // volatile read
  read y into register2
  ↓    // volatile read
  increment register1
  increment register2
  ↑    // volatile write
  write register1 into x
  ↑    // volatile write
  write register2 into y
}

这是一个很简单的例子。看看我的回答这里如何挥发性可以使在双重检查图案的差异。我用的是同一个箭头符号我这里使用的,可以很容易想象发生了什么。

This is a very trivial example. Look at my answer here for a non-trivial example of how volatile can make a difference in the double-checked pattern. I use the same arrow notation I used here to make it easy to visualize what is happening.

现在,我们也有 Thread.MemoryBarrier 法的工作。它生成一个完整的围墙。因此,如果我们用我们的箭头符号,我们可以想像如何工作的,以及。

Now, we also have the Thread.MemoryBarrier method to work with. It generates a full fence. So if we used our arrow notation we can visualize how that works as well.

考虑这个例子。

static int x = 0;
static int y = 0;

static void Main
{
  x++;
  Thread.MemoryBarrier();
  y++;
}

然后看起来是这样的,如果我们要展示的各个指令和以前一样。请注意,指令运动pvented现在一共$ P $。实在是没有别的办法可以在不影响指令的逻辑顺序得到执行。

Which then looks like this if we are to show the individual instructions as before. Notice that instruction movement is prevented altogether now. There is really no other way this can get executed without compromising the logical sequence of the instructions.

static void Main()
{
  read x into register1
  increment register1
  write register1 into x
  ↑    // Thread.MemoryBarrier
  ↓    // Thread.MemoryBarrier
  read y into register1
  increment register1
  write register1 into y
}

好了,多了一个例子。这一次,让我们用VB.NET。 VB.NET不具备挥发性关键字。那么怎样才能模仿挥发性读在VB.NET?我们将使用 Thread.MemoryBarrier 。 1

Okay, one more example. This time let us use VB.NET. VB.NET does not have the volatile keyword. So how can we mimic a volatile read in VB.NET? We will use Thread.MemoryBarrier.1

Public Function VolatileRead(ByRef address as Integer) as Integer
  Dim local = address
  Thread.MemoryBarrier()
  Return local
End Function

这是什么样子我们的箭头符号。

And this is what it looks like with our arrow notation.

Public Function VolatileRead(ByRef address as Integer) as Integer
  read address into register1
  ↑    // Thread.MemoryBarrier
  ↓    // Thread.MemoryBarrier
  return register1
End Function

需要注意的是,因为我们要模仿挥发性读取调用 Thread.MemoryBarrier 必须放置的是很重要的在的实际读。不要落入认为挥发性读是指新鲜读和挥发性写指犯写的陷阱。这不是它的工作原理,这当然不是什么规范描述。

It is important to note that since we want to mimic a volatile read the call to Thread.MemoryBarrier must be placed after the actual read. Do not fall into the trap of thinking that a volatile read means a "fresh read" and a volatile write means a "committed write". That is not how it works and it certainly is not what the specification describes.

更新:

在参照图像。

等待!我verifing,所有的写操作完成!

wait! I am verifing that all the Writes are finished!

等待!我验证所有的消费者都得到了电流   值!

wait! I am verifying that all the consumers have got the current value!

这是陷阱我在说什么。该声明并非完全准确。是的,在硬件级别上实现内存屏障可同步高速缓存一致性的线条,以及一个结果,上面的语句可能会发生什么情况有所准确acount。但是,挥发性什么都不做超过限制指令的运动。该规范说的什么关于从内存中加载值,或将其存储到内存中,在那个地方记忆障碍是地方。

This is the trap I was talking about. The statements are not completely accurate. Yes, a memory barrier implemented at the hardware level may synchronize the cache coherency lines and as a result the statements above may be somewhat accurate acount of what happens. But, volatile does nothing more than restrict the movement of instructions. The specification says nothing about loading a value from memory or storing it to memory at the spot where the memory barrier is place.

1 的有,当然,在 Thread.VolatileRead 内建了。而且你会发现,它的实现正是我在这里做。的

1There is, of course, the Thread.VolatileRead builtin already. And you will notice that it is implemented exactly as I have done here.