| 作者 |
内容 |
| winds-home |
一个Singleton模式的问题
这段Singleton模式的代码在《Java与模式》上边说是错的,《非程序员》中的那篇《Java中的Singleton模式》上边也说是错误的,可是我在多线程环境下运行没有什么问题啊?哪位帮忙看看怎么样能找到它的问题?
public class Test2 {
protected Test2(){
}
public static Test2 getInstance(){
if (instance == null) {
synchronized(Test2.class) {
if (instance == null) {
instance = new Test2();
}
}
}
return instance;
}
private static Test2 instance = null;
} |
| 02/12/19 13:23 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| smilemac |
回复:
一个Singleton模式的问题
主要与编译器的编译方式以及硬件平台对指令的优化有关.换句话说
,instance=new Test2()的执行次序不一定是你期望的那样,可能会先给
instance赋值,然后才构造,如果在构造时弹出一个异常,那么第一个if就有可
能出现错误.即使不出现异常,在先赋值后构造的情况下,第一个if依然可能导
致错误,试想,假设当前在临界区的线程在赋值后,构造前因某种原因一直得不
到调度,会出现什么情形. 所以,去掉第一个if就正确了. |
| 02/12/19 15:19 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| gigix |
回复:
一个Singleton模式的问题
Double-Checked
Locking模式在JAVA中实际上无法得到预期的效果,它仍然不能保证Singleton的正确性。原因简述如下:
1.
Java内存管理指出,只在两个线程在同一个对象上进行同步时,它才会保证一个线程B能够看到另一个线程A的改变,从而使得A线程的synchronized块对线程B变为原子(要么什么也不变,要么完全改好)。
2.
Java并不是一种顺序执行语言。我们会想象程序的执行会按照源代码的顺序执行。但是Java并不是如此。Java对编译器和虚拟机的要求是满足as-if-serial:也就是只要它能够达到和严格顺序执行一样的效果,指令执行的顺序可以随便安排。
由于以上两点,在我们的Double-Checked Locking模式中可能有这样的情况:
假设线程A在synchronized块内部,它分配了内存,但是还没有完全构建好Singleton.这时,B进入getInstance,由于if
(instance == null)
没有synchronized,所以它看到instance已经被分配,不为空,所以它跳过自己的synchronized块,直接返回指向一个部分创建好的对象。显然,在B线程中对该Singleton对象的操作将是不可预期的。
因此,Double-Checked
Locking模式在JAVA中实际上不能保证Singleton对象的正确创建和引用(在C++中则可以保证)。如果你需要在JAVA中保证多线程环境下Singleton模式的正确,就必须对“检查对象是否已创建”的语句进行同步(并相应地付出较高的代价)。或者,由于出现同步错误的情况非常罕见,也许你可以忽略它。
|
| 02/12/19 16:31 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| testx |
哪里有原文?
这个没问题啊,原文是这样吗?同步区的if判断是后来加上去的把,那个去掉才会有问题 |
| 02/12/19 21:34 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| smilemac |
回复:
一个Singleton模式的问题
Double-Checked Locking在c++中也不能确保产生正确结果,这本身就是一个错误的算法。 |
| 02/12/19 22:25 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| gigix |
为什么?
说说看,为什么DCL在C++中也不灵? |
| 02/12/20 11:06 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| smilemac |
回复: 为什么?
I didn't say that it can not work in C++, I said that it can not
ALWAYS work in C++.
Think about a SMP machine with big cache per processor.
In fact, the DC-locking pattern is right just only in Intel X86
likes
platfrom and using a platform-dependant language to compile without
optimizing option. Even in a RISC machine like Alpha, it also have
the chance to fail. |
| 02/12/20 13:38 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| gigix |
想起Bjarne
Stroustrup说的话
那天跟Bjarne一起喝茶的时候问他:我看不懂Loki里的Singleton该怎么办?他答我:Singleton这种东西,是人们用来展示自己的聪明用的,尤其是Loki…… |
| 02/12/20 16:27 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| smilemac |
不明白你的意思,singleton我觉得还是很有用的,动态创建的singleton我觉得在服务器程序设计中尤其有用,其实算法是次要的,重要的singleton这个概念.
你真牛,和Bjarne Stroustrup喝过茶.能给我搞张签名吗?呵呵. |
| 02/12/20 16:54 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| smilemac |
在一个Distributed
Program中实现Singleton是比较复杂的,不是我们讨论的问题,而且我认为在一个分布式系统中singleton的重要性要超过单机系统,能提供Bjarne谈话的全部资料吗?
|
| 02/12/20 17:20 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| gigix |
我还跟Ivar吃过饭呢
跟Bjarne的谈话内容,在明年第一期《程序员》上就可以看到。
Singleton当然很重要,但重要的部分(正如你所说)是概念。至于实现……在任何一种场景下,实现(或者使用)Singleton的难度,并不比从头开始做的难度更低。 |
| 02/12/24 11:11 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|
| smilemac |
羡慕中........
|
| 02/12/24 11:20 |
酷帖! 臭帖! 回复 |
|
酷帖评价: 臭帖评价: |
| 返回页首 |
|