根据MSDN:
volatile关键字表示某个字段可能被同时执行的多个线程修改.声明为volatile的字段不受编译器优化的约束,这些优化假定由单个线程进行访问.这可确保始终在字段中显示最新值.
请注意最后一句:
这可确保始终在字段中显示最新值.
但是,此关键字存在问题.
我已经读过它可以改变指令的顺序:
Run Code Online (Sandbox Code Playgroud)First instruction Second instruction Can they be swapped? Read Read No Read Write No Write Write No Write Read Yes! <----
这意味着John为一个易变的字段设置了一个值,后来 Paul想要阅读该字段,Paul正在获得旧的价值!
这是怎么回事?这不是主要的工作吗?
我知道还有其他解决方案,但我的问题是关于volatile关键字.
我(作为程序员)是否需要阻止使用此关键字 - 因为这种奇怪的行为?
我一直在阅读,以Full fences防止任何类型的指令重新排序或缓存围栏(通过memoryBarrier)
然后我读到了volatile 哪些会产生"半围栏":
volatile关键字指示编译器在每次从该字段读取时生成一个获取栅栏,并在每次写入该字段时生成一个释放栅栏.
acquire-fence
获取栅栏可防止其他读/写在栅栏前移动;
release-fence
释放栅栏可防止在栅栏后移动其他读/写.
有人可以用简单的英语向我解释这两句话吗?
(围栏在哪里?)
在这里得到一些答案后 - 我已经制作了一幅可以帮助每个人的图画 - 我想.
我有一个关于C#/ .NET中法律指令重新排序的问题.
让我们从这个例子开始吧.我们在某个类中定义了此方法,其中_a,_b和_c是字段.
int _a;
int _b;
int _c;
void Foo()
{
_a = 1; // Write 1
_b = 1; // Write 2
_c = 1; // Write 3
}
Run Code Online (Sandbox Code Playgroud)
我们的呼叫环境看起来像这样.
//memory operations
ClassInstance.Foo();
//memory operations
Run Code Online (Sandbox Code Playgroud)
我想知道当这个方法调用内联对函数调用时,什么样的法律指令重新排序是可能的.更具体地说,我想知道在Foo()中重新排序内存操作是否/何时合法,内存操作在其外部(来自我们之前的示例,//内存操作).
此外,函数调用(无内联)在某种意义上是"生成内存障碍".同样,在函数调用之前或之后发生的内存操作不能与函数调用中的内存操作重新排序.
如果是这样,当它被编译器内联时,它仍会有这种"内存屏障"行为吗?
fallowing子句来自jetbrains.net在阅读了这篇以及网上的其他文章后,我仍然不明白在第一个线程进入锁之后如何返回null.有人确实理解它可以帮助我并以更人性化的方式解释它吗?
"考虑以下代码:
public class Foo
{
private static Foo instance;
private static readonly object padlock = new object();
public static Foo Get()
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Foo();
}
}
}
return instance;
}
};
Run Code Online (Sandbox Code Playgroud)
给定上面的代码,初始化Foo实例的写入可以被延迟,直到写入实例值,从而产生实例返回处于单元化状态的对象的可能性.
为了避免这种情况,必须使实例值易变."