您的位置:首页 > 其它

单例模式之懒汉的并发问题,只需要添加一个 synchronized 就可以解决了

2017-02-26 12:26 344 查看
复现并发问题:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐