挥发性违反其主要工作? [英] Volatile Violates its main job?

查看:151
本文介绍了挥发性违反其主要工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 MSDN

  

volatile关键字表示字段可能被修改   正在执行的同时多线程。字段是   声明为volatile不受编译器优化,   假定由单个线程访问。这确保了最   最多最新的值是在任何时候都实地present。

请注意最后一句:

这确保了最先进的最新值是在任何时候都present在外地。

然而,有与此关键字的一个问题。

我已经 之能指令变更单:

 第一指令第二指令对它们进行交换?
阅读阅读无
读写无
写写否
写读是的! < ----
 

这意味着约翰设置一个值,以挥发性现场,和以后保罗想要阅读的领域, 保罗是获得值!

这是怎么回事吗?是不是它的主要工作?

我知道有其他的解决方案,但我的问题是关于volatile关键字。

我(作为程序员)应该需要prevent使用此关键字 - ?因为这种怪异的行为

解决方案

MSDN文档是错误的。这肯定不是什么挥发性一样。 C#的说明告诉你到底是什么挥发性不和得到一个鲜读或承诺写入是不是其中之一。该规范是正确的。 挥发性只保证在收购栅栏读取和释放,围栏上写。这些被定义为以下

  • 收购围栏:在其他的读取和写入,不准动的的围栏内存屏障
  • 发布围栏:在其他的读取和写入,不准移动内存屏障的 的围栏

我会尝试使用我的箭头符号说明表。一个↓箭头将迎来一个动荡的读取和↑箭头标记性写。没有指令可以通过移动箭头。想想箭头作为推动一切而去。

在我将使用变量如下分析; X 。我也认为他们都被标记为挥发性

案例#1

请注意的读取之后放置箭头​​ X $ P $从pvents的读向上。另请注意,的波动是无关紧要在这种情况下。

  VAR localx = X;
↓
VAR localy = Y;
↓
 

案例#2

请注意的读取之后放置箭头​​ X $ P $从pvents在写向上。还要注意,任的波动X ,但不能同时,可能已在这种情况下省略。

  VAR localx = X;
↓
↑
Y = 1;
 

案例#3

注意如何 y中的位置写入前的箭头 $ P $从pvents在写 X 向下移动。公告称,的波动X 是无关紧要在这种情况下。

 ↑
X = 1;
↑
Y = 2;
 

案例#4

请注意,还有就是 X 的读取写入之间没有障碍。正是因为如此,无论是写 X 可以向下浮动或 y的读可以飘起来。任一运动是有效的。这就是为什么在写 - 读案说明书可以调换。

 ↑
X = 1;
VAR localy = Y;
↓
 

值得注意提及

同样重要的是需要注意的是:

  • 在x86硬件上有写可变语义。
  • 在微软实施的CLI(和可疑Mono的为好)对写入可变语义。
  • 的ECMA规范中没有的没有的对写可变语义。

According to MSDN:

The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.

Please notice the last sentence:

This ensures that the most up-to-date value is present in the field at all times.

However, there's a problem with this keyword.

I've read that it can change order of instructions:

First instruction       Second instruction         Can they be swapped?
Read                         Read                         No
Read                         Write                        No
Write                       Write                         No 
Write                       Read                          Yes! <----

This means John sets a value to a volatile field, and later Paul wants to read the field, Paul is getting the old value!

What is going here ? Isn't that it's main job ?

I know there are other solutions, but my question is about the volatile keyword.

Should I (as a programmer) need to prevent using this keyword - because of such weird behavior ?

解决方案

The MSDN documentation is wrong. That is most certainly not what volatile does. The C# specification tells you exactly what volatile does and getting a "fresh read" or a "committed write" is not one of them. The specification is correct. volatile only guarantees acquire-fences on reads and release-fences on writes. These are defined as below.

  • acquire-fence: A memory barrier in which other reads and writes are not allowed to move before the fence.
  • release-fence: A memory barrier in which other reads and writes are not allowed to move after the fence.

I will try to explain the table using my arrow notation. A ↓ arrow will mark a volatile read and a ↑ arrow will mark a volatile write. No instruction can move through the arrowhead. Think of the arrowhead as pushing everything away.

In the following analysis I will use to variables; x and y. I will also assume that they are marked as volatile.

Case #1

Notice how the placement of the arrow after the read of x prevents the read of y from moving up. Also notice that the volatility of y is irrelevant in this case.

var localx = x;
↓
var localy = y;
↓

Case #2

Notice how the placement of the arrow after the read of x prevents the write to y from moving up. Also notice that the volatility of either of x or y, but not both, could have been omitted in this case.

var localx = x;
↓
↑
y = 1;

Case #3

Notice how the placement of the arrow before the write to y prevents the write to x from moving down. Notice that the volatility of x is irrelevant in this case.

↑
x = 1;
↑
y = 2;

Case #4

Notice that there is no barrier between the write to x and the read of y. Because of this the either the write to x can float down or the read of y can float up. Either movement is valid. This is why the instructions in the write-read case can be swapped.

↑
x = 1;
var localy = y;
↓

Notable Mentions

It is also important to note that:

  • x86 hardware has volatile semantics on writes.
  • Microsoft's implementation of the CLI (and suspect Mono's as well) has volatile semantics on writes.
  • The ECMA specification does not have volatile semantics on writes.

这篇关于挥发性违反其主要工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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