Double-checked locking and the Singleton pattern
2014-02-06 22:54
423 查看
Java单例模型非常常用,要实现单例,需要将相应的构造函数声明为private,然后通过静态方法getInstance()方法返回一个实例对象,这里有两种方法:
1、静态的对象直接初始化,调用静态方法getInstance()时直接返回
2、与1不同,对象的初始化是在getInstance()方法中完成的,其中getInstance()比较复杂,所用技术就是Double-checked locking
http://www.ibm.com/developerworks/java/library/j-dcl.html这篇文章详细讲解了Double-checked locking的来源以及出现的问题。
从程序代码角度来看,getInstance()可以完美的解决单例问题,既解决了首次方法调用的同步问题,同时也能保证以后的方法调用的未加入同步已解决性能问题。但文章指出事实并非如此,方法并不能完全保证方法的正确执行。其中涉及到构造函数instance = new Singleton()的底层实现:
instance可以在构造函数未执行前获得地址索引成non-null,当多个线程操作时变出现问题。这是编译器的乱序写问题,文章写于02年5月,其中提到的JIT compiler是Sun JDK 1.2.1,不是所有编译器都能够保证解决乱序写问题。
文章给出一个测试乱续写问题,验证String的不变性。不过本人用的是jdk6,跑了半天没跑出什么结果。
class StringCreator extends Thread {
文章最后指出单例模式最好选择两种方式:1、就是本文开始提到的第一种方法,2、是在getInstance()方法中初始化单例对象,但该方法需要声明为同步方法,即加个synchronized,优劣可想而知
1、静态的对象直接初始化,调用静态方法getInstance()时直接返回
import java.util.*; class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } }
2、与1不同,对象的初始化是在getInstance()方法中完成的,其中getInstance()比较复杂,所用技术就是Double-checked locking
import java.util.*; class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 if (instance == null) //2 instance = new Singleton(); //3 } } return instance; } }
http://www.ibm.com/developerworks/java/library/j-dcl.html这篇文章详细讲解了Double-checked locking的来源以及出现的问题。
从程序代码角度来看,getInstance()可以完美的解决单例问题,既解决了首次方法调用的同步问题,同时也能保证以后的方法调用的未加入同步已解决性能问题。但文章指出事实并非如此,方法并不能完全保证方法的正确执行。其中涉及到构造函数instance = new Singleton()的底层实现:
mem = allocate(); //Allocate memory for Singleton object. instance = mem; //Note that instance is now non-null, but //has not been initialized. ctorSingleton(instance); //Invoke constructor for Singleton passing //instance.
instance可以在构造函数未执行前获得地址索引成non-null,当多个线程操作时变出现问题。这是编译器的乱序写问题,文章写于02年5月,其中提到的JIT compiler是Sun JDK 1.2.1,不是所有编译器都能够保证解决乱序写问题。
文章给出一个测试乱续写问题,验证String的不变性。不过本人用的是jdk6,跑了半天没跑出什么结果。
class StringCreator extends Thread {
MutableString ms; public StringCreator(MutableString muts) { ms = muts; } public void run() { while (true) ms.str = new String("hello"); // 1 } } class StringReader extends Thread { MutableString ms; public StringReader(MutableString muts) { ms = muts; } public void run() { while (true) { if (!("hello".equals(ms.str))) // 2 { System.out.println("String is not immutable!"); break; } } } } class MutableString { public String str = "hello"; // 3 public static void main(String args[]) { MutableString ms = new MutableString(); // 4 new StringCreator(ms).start(); // 5 new StringReader(ms).start(); // 6 } }
文章最后指出单例模式最好选择两种方式:1、就是本文开始提到的第一种方法,2、是在getInstance()方法中初始化单例对象,但该方法需要声明为同步方法,即加个synchronized,优劣可想而知
相关文章推荐
- Double-checked locking and the Singleton pattern
- Double-checked locking and the Singleton pattern
- [转贴] Double-checked locking and the Singleton pattern
- 单例解析-Double-checked locking and the Singleton pattern
- Double-checked locking and the Singleton pattern
- Double-checked locking and the Singleton pattern
- Double-checked locking and the Singleton pattern
- Double-checked locking and the Singleton pattern--双重检查加锁失效原因剖析
- Singleton pattern and problem with double checked locking
- C++ and the Perils of Double-Checked Locking: Part II
- C++ and The Perils of Double-Checked Locking: Part I
- C++ and the Perils of Double-Checked Locking: Part II
- C++ and The Perils of Double-Checked Locking: Part I
- 获取单例对象 Double Checked Locking Pattern的危险性
- 双重检查锁定的漏洞的分析 The "Double-Checked Locking is Broken" Declaration
- Double-checked Locking (DCL) and how to fix it
- The "Double-Checked Locking is Broken" Declaration
- The "Double-Checked Locking is Broken" Declaration
- 双重检查锁定失败可能性——参照《The "Double-Checked Locking is Broken" Declaration》
- Singleton 单件模式及其变体 Double-Checked Locking 双重检查锁模式