多线程编程深入理解DCL的安全性

文章作者 100test 发表时间 2007:03:14 16:31:57
来源 100Test.Com百考试题网


对于双检锁,其实有多种不同的用法,有很多种用法是无论如何不会出现问题的.
我最初用双检锁来获取jndi对象时,立即有人告诉我双检锁是不安全的,我笑着告诉他:是否安全
我比你更有把握.

static DataSource ds = null.

public static DataSource getDataSource(){
if(ds == null){
synchronized(this.getClass()){
if(ds == null)
ds = xxx.
}
}

return ds.
}

这样的DCL有什么安全问题呢?它仅仅是为了不做重复的劳动.一是ds本身是已经存在的对象,不是动态
构造的,二是即使多次获取它也还是同一引用.这里做的工作仅仅是不想让另一个线程多做在JNDI上再查
找一次的工作,因为查找本身是耗时的,与其让另一个线程再查找还不如把它阻塞在synchronized外面什
么也不做.事实上即使是再查找一次两次获得的还是相同的引用,而且是已经构造好,不存在初始化问题
的对象.DCL会有什么安全问题?

所以不要一看到双检锁就认为它有安全问题.有些时候它完全可以非常好地工作.只是你要理解它的安全
问题到底在哪儿?


DCL到底有什么问题?

DCL的安全性最初被公开的时候在2001年JavaWorld.其实那个例子在那个时候已经是错误的.影响了后面几
代人都跟着错误.有时候我甚至不敢相信一些非常简单的问题因为放在权威的地方就没有人敢去责疑.

最初的问题提出者在这儿:http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html
例子是:
class SomeClass {
private Resource resource = null.

public Resource getResource() {
if (resource == null) {
synchronized {
if (resource == null)
resource = new Resource().
}
}
return resource.
}
}

我不知道提这个问题的人是否是个老古董.在2001年,JVM1.2已经发布好久了.JMM(Java Memory Model)已经
已经发布了新的规范,竟然在这个时候提出这样的问题.而且这个已经不存在的问题在此后的五年(今年是2006年)
中一误导着很多人,甚至是一些博士.

这个问题的提出者是这样说的.当一个线程运行到resource = new Resource().时,因为new一个对象需要分配空
间,初始化字段,调用构造方法.当为resource分配好空间后,外面的其它线程就可以看到不为null的resource,而这
时有可能还没有初始化字段和调用构造方法就被其它线程引用了.


相关文章


EJB应用从WebLogic到JBoss的迁移方法
J2EE综合svn配置手记
多线程编程深入理解DCL的安全性
为什么要始终使用PreparedStatement代替Statement?
跟我学Java之JavaGUI的发展和演化
澳大利亚华人论坛
考好网
日本华人论坛
华人移民留学论坛
英国华人论坛