对于需要双volatile修饰符检查锁定在.NET中 [英] The need for volatile modifier in double checked locking in .NET
问题描述
多文说,实施.NET双重检查锁定,当你锁定在球场上应该应用volatile修饰符。但是,到底为什么?考虑下面的例子:
Multiple texts say that when implementing double-checked locking in .NET the field you are locking on should have volatile modifier applied. But why exactly? Considering the following example:
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
为什么不锁(SyncRoot上)完成必要的内存一致性?是不是真的,经过锁定语句读取和写入会挥发,因此必要的一致性会实现呢?
why doesn't "lock (syncRoot)" accomplish the necessary memory consistency? Isn't it true that after "lock" statement both read and write would be volatile and so the necessary consistency would be accomplished?
推荐答案
挥发性是不必要的。嗯,有点**
Volatile is unnecessary. Well, sort of**
挥发性
用于创建一个内存屏障*之间读取和可变写道。结果锁定
,使用时,会导致各地块创建里面的内存屏障锁
,除了限制访问该块一个线程。结果
记忆障碍,使它所以每个线程读取变量(而不是在某个寄存器缓存本地值)的最大电流值,编译器不会重新排序的语句。使用挥发性
是不必要的,因为**你已经有了一个锁。
volatile
is used to create a memory barrier* between reads and writes on the variable.
lock
, when used, causes memory barriers to be created around the block inside the lock
, in addition to limiting access to the block to one thread.
Memory barriers make it so each thread reads the most current value of the variable (not a local value cached in some register) and that the compiler doesn't reorder statements. Using volatile
is unnecessary** because you've already got a lock.
约瑟夫阿尔巴哈利解释这个东西的方式比我以往任何时候都可以。
Joseph Albahari explains this stuff way better than I ever could.
和一定要检查出乔恩斯基特的指南,在C#
And be sure to check out Jon Skeet's guide to implementing the singleton in C#
结果
更新:结果
* 挥发性
导致变量的读取为 VolatileRead
和写入是 VolatileWrite
s,这在x86和x64上的CLR,都与一个内存屏障
实施。它们可以细粒上的其他系统。
update:
*volatile
causes reads of the variable to be VolatileRead
s and writes to be VolatileWrite
s, which on x86 and x64 on CLR, are implemented with a MemoryBarrier
. They may be finer grained on other systems.
**我的回答如果你正在使用的x86和x64处理器的CLR是唯一正确的。它的可能的是在其他内存模型真实,就像单声道(及其他实现),Itanium64和未来的硬件。这就是乔恩是指在他的文章中的陷阱双检查锁定。
**my answer is only correct if you are using the CLR on x86 and x64 processors. It might be true in other memory models, like on Mono (and other implementations), Itanium64 and future hardware. This is what Jon is referring to in his article in the "gotchas" for double checked locking.
做的一个{标记变量挥发性
与 Thread.VolatileRead
阅读它,或插入电话到 Thread.MemoryBarrier
}可能为code到处于弱势的内存模型情况正常工作是必要的。
Doing one of {marking the variable as volatile
, reading it with Thread.VolatileRead
, or inserting a call to Thread.MemoryBarrier
} might be necessary for the code to work properly in a weak memory model situation.
据我了解,在CLR(即使在IA64),写永远不会重新排序(总是写有释放的语义)。然而,IA64,读取可能会重新排序来以前写的,除非它们被标记不稳定。 Unfortuantely,我没有获得IA64硬件一起玩,所以什么我说一下这将是炒作。
From what I understand, on the CLR (even on IA64), writes are never reordered (writes always have release semantics). However, on IA64, reads may be reordered to come before writes, unless they are marked volatile. Unfortuantely, I do not have access to IA64 hardware to play with, so anything I say about it would be speculation.
我还发现这些文章有所帮助:搜索
<一href=\"http://www.$c$cproject.com/KB/tips/MemoryBarrier.aspx\">http://www.$c$cproject.com/KB/tips/MemoryBarrier.aspx
万斯·莫里森的文章(一切都指向这一点,它谈论双重检查锁定)结果
克里斯brumme的文章(一切链接到本)结果
<一href=\"http://www.bluebytesoftware.com/blog/PermaLink,guid,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx\">Joe达菲:双残破的变体检查锁定
i've also found these articles helpful:
http://www.codeproject.com/KB/tips/MemoryBarrier.aspx
vance morrison's article (everything links to this, it talks about double checked locking)
chris brumme's article (everything links to this)
Joe Duffy: Broken Variants of Double Checked Locking
路易斯·阿伯对多线程给予的概念很好的概述太结果系列
<一href=\"http://msmvps.com/blogs/luisabreu/archive/2009/06/29/multithreading-load-and-store-reordering.aspx\">http://msmvps.com/blogs/luisabreu/archive/2009/06/29/multithreading-load-and-store-reordering.aspx
<一href=\"http://msmvps.com/blogs/luisabreu/archive/2009/07/03/multithreading-introducing-memory-fences.aspx\">http://msmvps.com/blogs/luisabreu/archive/2009/07/03/multithreading-introducing-memory-fences.aspx
luis abreu's series on multithreading give a nice overview of the concepts too
http://msmvps.com/blogs/luisabreu/archive/2009/06/29/multithreading-load-and-store-reordering.aspx
http://msmvps.com/blogs/luisabreu/archive/2009/07/03/multithreading-introducing-memory-fences.aspx
这篇关于对于需要双volatile修饰符检查锁定在.NET中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!