《Java与模式》在讲Lazy Singleton时,提到在c++单例中广泛使用的double-checl locking,在java中确实无效的:
“在Java编译器中,LazySingleton类的初始化与m_instance变量赋值的顺序不可预料。如果一个线程在没有同步化的条件下读取m_instance引用,并调用这个对象的方法的话,可能会发现对象的初始化过程尚未完成,从而造成崩溃。”
public classLazySingleton {
private staticLazySingleton m_instance = null;
privateLazySingleton() {
}
public staticLazySingleton getInstance() {
if(m_instance==null) {
synchronized (LazySingleton.class) {
if(m_instance==null) {
m_instance=new LazySingleton();
}
}
}
returnm_instance;
}
}
这段话是说,是jvm执行时会对便以后的字节码重排序(reordering),最坏的情况下,当m_instance被赋值以后(不为null,过了里面的那层检查),LazySingleton类其实还没有完成初始化,那么对m_instance中成员的访问就会导致错误。当然这种是极少发生的,在这个问题被发现之前java的double-check locking也曾大行其道。
阎宏写《Java与模式》的时候java还在1.4的版本。当java1.5发布以后,情况发生了一点改变。java的double check也是可行的了。只要LazySingleton的所有instance field都是immutable的话,就能保证成功了。在Java5之后,有一个所谓的“happens-before”的概念,在每一个构造函数结束的地方都有一个freeze动作,在构造函数返回前,所有的final成员变量都要完成初始化。使用volatile来修饰static的m_instance也可以保证成功,然而一些jvm并没有正确实现volatile语义,所以这种发放还不是那么保险。官方的说法是:
"In JVMs prior to 1.5, volatile would not ensure that it worked (your mileage may vary). Under the new memory model, making the instance field volatile will "fix" the problems with double-checked locking, because then there will be a happens-before relationship
between the initialization of the Something by the constructing thread and the return of its value by the thread that reads it."
按照java专家们的习惯,java中会出问题的东西,一定是不好的东西。JSR 166专家组说,double-checked locking是一种不好的发明,现在已经被广泛废弃。替代是Lazy initialization holder,提供了同样的好处,也更容易理解。Effective Java中有个例子
public classFoo {
private static classFooHolder {
static finalFoo foo=new Foo();
}
public staticFoo getFoo() {
returnFooHolder.foo;
}
}
这是个很triky的方法,利用了jvm类加载时的特性,第一次使用FooHolder时才进行初始化。不得不承认,看起来确实比double-checked locking简单舒服一些。
http://hi.baidu.com/%BA%FA%D2%E7%D1%F3/blog/item/24e14e4aeabd762b09f7ef81.html
分享到:
相关推荐
C++ and the Perils of Double-Checked Locking 关于单例模式C++实现的一些问题
C++ and the Perils of Double Checked Locking.zip
USB Type-C Locking Connector Specification
Taking advantage of the dispersive Fourier transformation technique, the decaying evolution processes of double-pulse mode-locking in a single-walled carbon-nanotube-based Er-doped fiber laser are ...
Laravel开发-laravel-locking 提供锁定机制
资源来自pypi官网。 资源全名:django-db-locking-2.0.0.tar.gz
Supporting Fine-Granularity Locking and Partial Rollbacks Using Write-Ahead LoggingC. MOHANIBM Almaden Research CenterandDON HADERLEIBM Santa Teresa LaboratoryandBRUCE LINDSAY, HAMID PIRAHESH and ...
MySQL的配置文件my.cnf中默认存在一行skip-external-locking的参数,即“跳过外部锁定”。根据MySQL开发网站的官方解释,External-locking用于多进程条件下为MyISAM数据表进行锁定。 如果你有多台服务器使用同一个...
Mode-locking of a terahertz laser by direct phase synchronization
这个小程序涉及到了以下知识点: Java基础知识 队列《数据结构》 单例模式“双检锁/双重校验锁(DCL,即 double-checked locking)”
High-repetition-rate pulse generation using dual-mode self-injection locking in a Fabry-Perot laser diode
A new technique for seed-injection locking of single-axial-mode (SAM) Q-switched Nd:YAG laser is reported. The technique called energy reduction (ER) is utilized when SAM operation is locked to design...
The Q-switched mode-locking opticalparametric oscillator with intra cavity
比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但...
As a novel practical method to realize single-polarization operation of fiber distributed Bragg reflector (DBR) laser, we proposed self-injection locking (SIL) with an active fiber ring feedback ...
一本面向想要了解SQL Server并发性以及如何解决过多的阻塞或死锁问题的DBA和开发人员的书。
Here we fabricated large-core (LC) double-cladding Tm-doped silica fiber via the sol-gel method. The sol-gel-fabricated Tm-doped silica (SGTS) fiber had a large core diameter of 30 μm with a high ...
锁机制的论文,在jdk1.6以后引入的偏向锁技术大大增加了以往重锁sychronized的性能
Self-Locking Avoidance and Stiffness Compensation of a Three-Axis Micromachined Electrostatically Suspended Accelerometer