线程安全的单例模式

这几天写到一个监听session的功能,其中涉及到了单例模式的线程安全,但是最开始的代码同事说有问题,代码如下:

1     private static SessionManager instance;
2 
3     public static SessionManager getInstance() {
4         if (instance == null) {
5             instance = new SessionManager();
6         }
7         return instance;
8     }

这种单例就是我记得的懒汉单例,这种单例模式是线程不安全的,即:在多线程时,并不能保证这个类只被实例化一次。解决这个问题需要加锁,代码如下:

1     private static SessionManager instance;
2 
3     public static synchronized SessionManager getInstance() {
4         if (instance == null) {
5             instance = new SessionManager();
6         }
7         return instance;
8     }

通过增加synchronized关键字到getInstance()方法中,迫使每个线程在进入方法之前,要先等别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。

这种方法存在的问题:当设置好instance变量后,就不再需要同步这个方法了,之后每次调用这个方法,同步都是一种浪费。

所以我们可以在getInstance中进行加锁判断,代码如下:

 1     private static SessionManager instance;
 2 
 3     public static SessionManager getInstance() {
 4         if (instance == null) {
 5             synchronized (SessionManager.class) {
 6                 if (instance == null) {
 7                     instance = new SessionManager();
 8                 }
 9             }
10         }
11         return instance;
12     }

这种方法据说会因为java的无序写入失效,所以还是建议使用饿汉单例,代码如下:

1     private static SessionManager instance = new SessionManager();
2 
3     public static SessionManager getInstance() {
4         return instance;
5     }

使用这种方法,JVM在加载这个类时会马上创建唯一的单例实例,所以是线程安全的。

原文地址:https://www.cnblogs.com/dsgzxy527/p/3557259.html