专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
Java编程精选  ·  Controller层代码这么写,简洁又优雅! ·  昨天  
Java编程精选  ·  字节员工自曝:在强调一遍OD ... ·  2 天前  
Java编程精选  ·  雷军删文,热搜第一! ·  3 天前  
51好读  ›  专栏  ›  ImportNew

可以不要再使用 Double-Checked Locking 了

ImportNew  · 公众号  · Java  · 2017-07-14 12:00

正文

请到「今天看啥」查看全文


helper = new Helper();

return helper;

}

// other functions and members...

}


这段代码如果运行在多线程环境下,将会出现问题。很显然的一个问题,两个或者多个Helper对象将会被分配内存,其他问题我们会在后面提到,我们先简单的给方法加一个synchronized关键字。


// Correct multithreaded version

class Foo {

private Helper helper = null;

public synchronized Helper getHelper() {

if (helper == null)

helper = new Helper();

return helper;

}

// other functions and members...

}


上面的代码在每次调用getHelper方法的时候都要进行同步,下面的Double-Checked Locking方式避免了当Helper对象被实例化之后再次进行同步:


// Broken multithreaded version

// "Double-Checked Locking" idiom

class Foo {

private Helper helper = null;

public Helper getHelper() {

if (helper == null)

synchronized(this) {

if (helper == null)

helper = new Helper();

}

return helper;

}

// other functions and members...

}


不幸的是,这段代码在存在编译优化或多处理器共享内存的情况下不能够正常工作。


二、Double-Checked Locking不能够正常工作


为什么上文说Double-Checked Locking不能够正常工作有很多的原因,我们将会描述一对很显而易见的原因。通过理解存在的问题,我们尝试着去修复Double-Checked Locking存在的问题,然而我们的修复可能并没有用,我们可以一起看看为什么没有用,理解这些原因,我们去尝试着寻找更好的方法,可能还是没有用,因为还是存在一些微妙的原因。


1)第一个不能正常工作的原因


Double-Checked Locking不能够正常工作的一个很显然的原因是对helper属性的写指令和初始化Helper对象的指令可能被冲排序,因此当其他线程再次调用getHelper方法的时候,将会得到一个没有被初始化完成的Helper对象,如果这个线程访问了这个对象没有被初始化的属性,那么就会出现位置错误。


我们来看看对于下面这行代码,在Symantec JIT编译器环境下的指令重排序的例子:


singletons[i].reference = new Singleton();


下面是实际执行的代码:


0206106A   mov         eax,0F97E78h

0206106F   call        01F6B210                  ; allocate space for

; Singleton, return result in eax







请到「今天看啥」查看全文


推荐文章
Java编程精选  ·  Controller层代码这么写,简洁又优雅!
昨天
Java编程精选  ·  雷军删文,热搜第一!
3 天前
21世纪经济报道  ·  华润退出深铁接盘!万科股权之争走向尾声
8 年前
灼见  ·  请远离那些假的舒适区
8 年前