java单例模式的线程安全有关问题

java单例模式的线程安全问题

最近在学习设计模式,在看到单例时突然想到如果在多线程的情况下会导致出错(多个线程同时进行操作)。因此赶紧放狗去搜。终于找到了一段据说可以实现线程安全的单例程序。我把它贴出来,希望有人能解答我的疑惑。

Java代码 java单例模式的线程安全有关问题
  1. package net.chopsuey.singleton;   
  2.   
  3. public class Singleton   
  4. {   
  5.     private static class SingletonHolder   
  6.     {   
  7.         static Singleton instance = new Singleton();   
  8.     }   
  9.   
  10.     public static Singleton getInstance()   
  11.     {   
  12.         return SingletonHolder.instance;   
  13.     }   
  14. }  
package net.chopsuey.singleton;

public class Singleton
{
    private static class SingletonHolder
    {
        static Singleton instance = new Singleton();
    }

    public static Singleton getInstance()
    {
        return SingletonHolder.instance;
    }
}

 我如何才能知道这段代码就是线程安全的呢?有谁能帮忙写个测试代码给我测试一下吗?最好是有屏幕输出语句的。


问题补充:
首先非常感谢各位的关注。但我已经弄明白了。把我的意见贴出来大家交流一下。
单例设计模式有两种形式:一种是饥饿式

Java代码 java单例模式的线程安全有关问题
  1. package net.chopsuey.singleton;   
  2.   
  3. public final class EagerSingleton   
  4. {   
  5.     private static EagerSingleton singObj = new EagerSingleton();   
  6.   
  7.     private EagerSingleton()   
  8.     {   
  9.     }   
  10.   
  11.     public static EagerSingleton getSingleInstance()   
  12.     {   
  13.         return singObj;   
  14.     }   
  15. }  
package net.chopsuey.singleton;

public final class EagerSingleton
{
    private static EagerSingleton singObj = new EagerSingleton();

    private EagerSingleton()
    {
    }

    public static EagerSingleton getSingleInstance()
    {
        return singObj;
    }
}



比较明显,这种是线程安全的。因为static变量是在类被加载时(有可能没被实例化)初始化并仅被初始化一次。因为这样就可以保证只有一个singObj被初始化。

另外一种则是懒汉式

Java代码 java单例模式的线程安全有关问题
  1. package net.chopsuey.singleton;   
  2.   
  3. public final class LazySingleton   
  4. {   
  5.     private static LazySingleton singObj = null;   
  6.   
  7.     private LazySingleton()   
  8.     {   
  9.     }   
  10.   
  11.     public static LazySingleton getSingleInstance()   
  12.     {   
  13.         if (singObj == null)   
  14.         {   
  15.             singObj = new LazySingleton();   
  16.         }   
  17.         return singObj;   
  18.     }  
package net.chopsuey.singleton;

public final class LazySingleton
{
    private static LazySingleton singObj = null;

    private LazySingleton()
    {
    }

    public static LazySingleton getSingleInstance()
    {
        if (singObj == null)
        {
            singObj = new LazySingleton();
        }
        return singObj;
    }



这种则是线程不安全的了。因为当有多个线程一起调用getSingleInstance()时则可能会生成多个实例。因此才需要修改一下。修改为我之前的那段代码

Java代码 java单例模式的线程安全有关问题
  1. package net.chopsuey.singleton;     
  2.     
  3. public class Singleton     
  4. {     
  5.     private static class SingletonHolder     
  6.     {     
  7.         static Singleton instance = new Singleton();     
  8.     }     
  9.     
  10.     public static Singleton getInstance()     
  11.     {     
  12.         return SingletonHolder.instance;     
  13.     }     
  14. }  
package net.chopsuey.singleton;  
 
public class Singleton  
{  
    private static class SingletonHolder  
    {  
        static Singleton instance = new Singleton();  
    }  
 
    public static Singleton getInstance()  
    {  
        return SingletonHolder.instance;  
    }  
}


一个静态内部类内的一个静态成员就可以保证它只在类被加载时只初始化一次。因此不管有多少个线程来调用它,都只能得到同个实例(类被加载时初始化的那个)。