双重检查锁定物品
我正在阅读关于“双重检查锁定”的这篇文章在文章的主题之外,我想知道为什么在文章的某些时候作者使用了下一个习语:
清单 7. 尝试解决乱序写入问题
public static Singleton getInstance() { if (实例 == null) { 同步(Singleton.class){//1 单例inst=实例; //2 if (inst == null) { 同步(Singleton.class){//3 inst = new Singleton(); //4 } 实例=实例; //5 } } } 返回实例; }
我的问题是: 是否有任何理由使用同一个锁同步两次某些代码? 这有什么目的吗?
提前谢谢了。
I was reading this article about "Double-Checked locking" and out of the main topic of the article I was wondering why at some point of the article the author uses the next Idiom:
Listing 7. Attempting to solve the out-of-order write problem
public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 Singleton inst = instance; //2 if (inst == null) { synchronized(Singleton.class) { //3 inst = new Singleton(); //4 } instance = inst; //5 } } } return instance; }
And my question is:
Is there any reason to synchronize twice some code with the same lock?
Have this any purpose it?
Many thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
遵循 John Skeet 建议:
这是第二个同步块的关键:
因此,基本上,使用内部同步块,我们试图“欺骗”JMM 在同步块内创建实例,以强制 JMM 在同步块完成之前执行该分配。 但这里的问题是,JMM 正在引导我们,并将同步块之前的分配移到同步块内,将我们的问题移回到开头。
这是我从这些文章中了解到的,非常有趣,再次感谢您的回复。
Following the John Skeet Recommendation:
And here is the key for the second sync block:
So basically, with the Inner sync block, we are trying to "cheat" the JMM creating the Instance inside the sync block, to force the JMM to execute that allocation before the sync block finished. But the problem here is that the JMM is heading us up and is moving the assigment that is before the sync block inside the sync block, moving our problem back to the beginnig.
This is what i understood from those articles, really interesting and once more thanks for the replies.
好吧,但是文章说
而且似乎 JVM 还对 ASM 中的“伪代码”进行了下一个翻译:
到目前为止,“instance=inst”之后的不写入点还没有实现吗?
我现在将阅读这篇文章,感谢您的链接。
All right, but the article said that
And also seems like the JVM makes the next translation to "pseudo-code" in ASM:
So far, the point of no writes after the "instance=inst" is not accomplished?
I will read now the article, thanks for the link.
从 Java 5 开始,您可以通过将字段声明为 volatile 来进行双重检查锁定。
请参阅 http://www.cs.umd.edu/~pugh /java/memoryModel/DoubleCheckedLocking.html 以获得完整的解释。
Since Java 5, you can make double-checked locking work by declaring the field volatile.
See http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html for a full explanation.
关于这个习惯用法,有一篇非常建议和澄清的文章:
http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html?page=1
另一方面,我认为 dhighwayman.myopenid 的意思是为什么作者将一个引用同一类 (synchronized(Singleton.class)) 的同步块放在引用同一类的另一个同步块中。 当在该块内创建一个新实例(Singleton inst = instance;)时,可能会发生这种情况,并且为了保证它是线程安全的,有必要编写另一个同步。
否则我看不出任何意义。
Regarding this idiom there is a very advisable and clarifying article:
http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html?page=1
On the other hand, I think what dhighwayman.myopenid means is why the writer has put one synchronized block referring to the same class (synchronized(Singleton.class)) within another synchronized block referring to the same class. It may happen as a new instance (Singleton inst = instance;) is created within that block and to guarantee it to be thread-safe it's necessary to write another synchronized.
Otherwise, I can't see any sense.
请参阅有关 Java 内存模型的 Google 技术讲座,了解更精细的内容JMM 的要点。 由于这里缺少它,我还想指出 Jeremy Mansons 博客 'Java Concurrency' 特别是。 关于双重检查锁定的帖子(任何在Java 世界似乎有一篇关于此的文章:)。
See the Google Tech Talk on the Java Memory Model for a really nice introduction to the finer points of the JMM. Since it is missing here, I would also like to point out Jeremy Mansons blog 'Java Concurrency' esp. the post on Double Checked locking (anyone who is anything in the Java world seems to have an article on this :).
对于 Java 5 及更高版本,实际上有一个双重检查变体,它比同步整个访问器更好。 双重检查锁定声明中也提到了这一点:
这里的关键区别是在变量声明中使用易失性 - 否则它不起作用,并且无论如何它在Java 1.4或更低版本中不起作用。
For Java 5 and better there is actually a doublechecked variant that can be better than synchronizing the whole accessor. This is also mentioned in the Double-Checked Locking Declaration :
The key difference here is the use of volatile in the variable declaration - otherwise it does not work, and it does not work in Java 1.4 or less, anyway.
锁定两次的目的是尝试防止乱序写入。 内存模型指定了重新排序可以发生的位置,部分是通过锁来实现的。 该锁确保在“instance = inst;”之后不会出现任何写入操作(包括单例构造函数内的任何写入操作)。 线。
然而,为了更深入地探讨这个主题,我推荐 Bill Pugh 的文章。 然后永远不要尝试:)
The point of locking twice was to attempt to prevent out-of-order writes. The memory model specifies where reorderings can occur, partly in terms of locks. The lock ensures that no writes (including any within the singleton constructor) appear to happen after the "instance = inst;" line.
However, to go deeper into the subject I'd recommend Bill Pugh's article. And then never attempt it :)
本文指的是 5.0 之前的 Java 内存模型 (JMM)。 在该模型下,留下同步块会强制写入主内存。 因此,这似乎是为了确保 Singleton 对象在引用它之前被推出。 然而,它并不太有效,因为对实例的写入可以向上移动到块 - roach motel 中。
然而,5.0 之前的模型从未正确实现。 1.4应该遵循5.0模型。 类是惰性初始化的,所以你最好只写
或者更好,不要使用单例,因为它们是邪恶的。
The article refers to the pre-5.0 Java memory model (JMM). Under that model leaving a synchronised block forced writes out to main memory. So it appears to be an attempt to make sure that the Singleton object is pushed out before the reference to it. However, it doesn't quite work because the write to instance can be moved up into the block - the roach motel.
However, the pre-5.0 model was never correctly implemented. 1.4 should follow the 5.0 model. Classes are initialised lazily, so you might as well just write
Or better, don't use singletons for they are evil.
Jon Skeet 是对的:请阅读 Bill Pugh 的 文章。 汉斯使用的习语是不起作用的精确形式,因此不应使用。
这是不安全的:
这也是不安全的:
永远不要做其中任何一个。
相反,同步整个方法:
除非您每秒检索该对象无数次,否则实际上对性能的影响可以忽略不计。
Jon Skeet is right: read Bill Pugh's article. The idiom that Hans uses is the precise form that won't work, and should not be used.
This is unsafe:
This is also unsafe:
Don't do either of them, ever.
Instead, synchronise the whole method:
Unless you're retrieving this object a zillion times a second the performance hit, in real terms, is negligible.
我在这里介绍了一些内容:
http://tech.puredanger .com/2007/06/15/double-checked-locking/
I cover a bunch of this here:
http://tech.puredanger.com/2007/06/15/double-checked-locking/