复现并发问题:
package review.bank;
/**
* Created by kodulf on 2017/2/26.
*/
public class SingleInstanceLazyMan {
private SingleInstanceLazyMan(){
}
static SingleInstanceLazyMan singleInstanceLazyMan ;
//synchronized 如果不添加,那么会出现三个进程一起调度的情况
public static SingleInstanceLazyMan getInstance(){
if(singleInstanceLazyMan==null){
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
singleInstanceLazyMan = new SingleInstanceLazyMan();
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
}
return singleInstanceLazyMan;
}
}
新建三个进程去调用这个单例的getInstance方法
public static void testSingleInstance(){
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
SingleInstanceLazyMan.getInstance();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
SingleInstanceLazyMan.getInstance();
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
SingleInstanceLazyMan.getInstance();
}
});
thread1.start();
thread2.start();
thread3.start();
}运行结果:会发现都调用了if == null的那个判断了,就是执行了里面的程序了
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-0
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-1
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
before new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-1
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
after new Thread-2
Process finished with exit code 0
要解决这个问题:
只需要添加一个单词,synchronized 就可以了
package review.bank;
/**
* Created by zhangyinshan on 2017/2/26.
*/
public class SingleInstanceLazyMan {
private SingleInstanceLazyMan(){
}
static SingleInstanceLazyMan singleInstanceLazyMan ;
//synchronized 如果不添加,那么会出现三个进程一起调度的情况
public static synchronized SingleInstanceLazyMan getInstance(){
if(singleInstanceLazyMan==null){
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
System.out.println("before new "+Thread.currentThread().getName());
singleInstanceLazyMan = new SingleInstanceLazyMan();
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
System.out.println("after new "+Thread.currentThread().getName());
}
return singleInstanceLazyMan;
}
}
运行结果:只调用了一次,这个就是我们想要的
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
before new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
after new Thread-0
Process finished with exit code 0
该博客讨论了在并发环境中懒汉式单例模式可能遇到的问题,通过实例展示了当多个线程同时调用 getInstance 方法时,可能导致多次实例化。博主提出,只需在 getInstance 方法上添加 synchronized 关键字,即可确保线程安全,实现单例的正确创建。
1019

被折叠的 条评论
为什么被折叠?



