复现并发问题:
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