这把锁有必要吗?

eseasky 06-08-27
         

今天有空看了Double-checked locking and the Singleton pattern这篇文章.当看到
Double-checked locking: Take two

Given that the current double-checked locking code does not work, I've put together another version of the code, shown in Listing 7, to try to prevent the out-of-order write problem you just saw.


Listing 7. Attempting to solve the out-of-order write problem
这里时产生一个疑问.

         

eseasky
2006-08-27 13:05

不好意思,问题没说完还,继续说

对下面代码
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;
}
中的第二把锁是不是有必要的问题,个人认为可以将上面代码改成如下:
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
Singleton inst = instance; //2
if (inst == null)
{
inst = new Singleton(); //3

instance = inst; //4
}
}
}
return instance;
}


我分析了一下,修改后的代码一样能实现解决"solve the out-of-order write problem" 的目的,同时跟修改前相比少一把锁的开销.
个人浅见,还望各位高手不吝指正,谢谢!

banq
2006-08-28 10:37

单态问题在实际中一般是回避的。

对象都是有生命周期的,没有一个永恒的对象,只有对象有生命周期,软件才有生命,所以使用单态很容易强行扭曲对象的生命周期,使其“万岁”。

更何况单态的双锁研究,就象研究数据库连接池一样,意义不大,个人意见。

luyinquan
2006-08-28 16:54

更何况单态的双锁研究,就象研究数据库连接池一样,意义不大,个人意见。
小弟不懂
请问baql大师怎么理解,数据库连接用连接池很多,为何连接池的意义不大?

banq
2006-08-29 10:16

不是大师,个人意见。

软件研究需要站在前人基础上,从模式入手、注重应用,数据库连接池是一种Pool模式,现在J2EE应用中,Pool模式是一个基本基础模式,必然需要使用的,我们精力放在模式使用场景研究上即可,如果将精力放在数据库连接池如何做上面,而不是如何用,显然将关注焦点对错了。

这种思维方式其实在很多人身上有,我以前举例过,大师候捷曾经发表一篇Collection内部字节码研究文章,这显然也是向内部关注的思维习惯,我们的精力有限,如果不注重如何使用,也就是模式,软件领域那么技术,不可能也没有必要逐个打开它们,看它们内部原理,换在10年前,我们还可以打开汇编语言或二进制代码研究一下原理,现在几乎不可能,就只能将其作为一个Box,探讨Box应用场景,我们称之为模式。

所以,我个人总结了:搞Java需要有一个向上拔高的思维,也就是架构模式思维,你不会做数据库连接池,但是你知道有池模式,你会用,而且用得恰到好处,后者就是关键了。

回到双锁上面来,单态是邪恶的已经在本站讨论过,单态模式其实是反模式,不是模式,现在我们都使用容器来管理对象生命,对象都是鲜活的,而不是一个全局变量或死鱼一个。

那么基于单态实现的双锁是否有效,能否达到真正单态等研究都意义不大,而且会陷入象数据库;连接池如何实现那样的怪圈。

以上只是个人意见,权当参考。