前提是在单容器下。听说方法四要加 volatile  才安全,为什么?或者其他方法也有什么不安全的请指正?package com.aa;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Singleton {
private static Singleton singleton=null;
private static Lock lock=new ReentrantLock();
/*
 * 方法一 lazy init
 */
public static Singleton getInstance1(){
lock.lock();
try{
if(singleton==null){
singleton=new Singleton();
}
}finally{
lock.unlock();
}
return singleton;
}

/*
 * 方法二 lazy init
 */
public synchronized static Singleton getInstance2(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}

/*
 * 方法三
 */
private static Singleton singleton3=new Singleton();
public static Singleton getInstance3(){
return singleton3;
}

/*
 * 方法四
 */
private volatile static Singleton singleton4;

public static Singleton getInstance4(){
if(singleton4==null){
synchronized (Singleton.class) {
if(singleton4==null){
singleton4=new Singleton();
}
}
}
return singleton4;
}

public static void main(String[] args) {
new Thread("threadA"){
public void run(){
Singleton.getInstance3();
}
}.start();
new Thread("threadB"){
public void run(){
Singleton.getInstance3();
}
}.start();
}
}

解决方案 »

  1.   

    http://www.100720.com/java_2011_09_08_1810.html
    不能工作的基本原因在于,在java编译器中Singleton的初始化与singleton4变量的赋值顺序不可预料。
      

  2.   

    不加 volatile,Singleton类的初始化与变量Singleton4的初始化顺序不定,new的时候异常
      

  3.   

     感觉还是这个volatile 关键字在线程中的作用吧。因为在第二种于第四种方式中都使用了同步。其他的方式都没有使用,也就是说安全性的话,其他的肯定没有二和四安全。
      volatile的我也没有使用过,网上是这么说的“一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份”
      

  4.   

    double check lock在某些情况下貌似也不是安全的,《effective java》上说enum实现单例最好