您的位置:首页 > 编程语言 > Java开发

单例模式的懒汉式在多线程的问题

2017-09-20 16:44 232 查看
转载自:http://www.cnblogs.com/sevenlin/p/sevenlin_thread20150809.html

我们都知道,单例设计模式中有两种方法,一种是饿汉式,另外一种就是懒汉式,具体如下:

package com.seven.exercise.testEception;

/**
* 单例模式,饿汉式
* @author Seven
*
*/
public class SingleDemoHunger {

private SingleDemoHunger() {

}

private static SingleDemoHunger sdh = new SingleDemoHunger();

public static SingleDemoHunger getInstance() {
return sdh;
}

}

懒汉式:

package com.seven.exercise.testEception;

/**
* 懒汉式
* @author Seven
*
*/
public class SingleDemo {

/**
* 私有化构造函数
*/
private SingleDemo(){

}

private static SingleDemo singleDemo = null;

/**
* 提供获取实例的方法
* @return
*/
public static SingleDemo getInstance(){
if(singleDemo==null){
singleDemo = new SingleDemo();
}
return singleDemo;
}
}


相信这两种方法大家都知道,但是没有有考虑过在多线程的情况下:

饿汉式属于立即加载,所以不存在在多线程中出现错误的情况;

但是懒汉式的话就有可能出现问题了,如多一个线程执行到判断是否为空的语句
if(singleDemo==null)


的时候,当前线程被阻塞,而第二个线程进来了,这样的话第二个线程创建了新的对象,那么第一个线程被唤醒的时候又创建多一个对象,这样在内存中就存在了两个对象,明显和单例设计模式不符,那么我们应该怎么做呢?

很简单,用 synchronized关键字就可以轻松解决:

package com.seven.exercise.testEception;

/**
* 懒汉式
* @author Seven
*
*/
public class SingleDemo {

/**
* 私有化构造函数
*/
private SingleDemo(){

}

private static SingleDemo singleDemo = null;

/**
* 提供获取实例的方法,用synchronized来解决多线程的问题.
* @return
*/
public static SingleDemo getInstance(){
synchronized (SingleDemo.class) {
if(singleDemo==null){
singleDemo = new SingleDemo();
}
}
return singleDemo;
}

}

这样就减少了创建多个实例的可能,但是还是存在创建多个实例的可能性,而且同步锁肯定要消耗资源,这样的话就会降低效率,那么有什么办法可以提高效率呢?答案是有的,那就是通过二次判断,这样的话就不用每次都执行同步代码块,这样的话,只需第一次执行的时候比较占资源,以后的话就和之前的一样了:
package com.seven.exercise.testEception;

/**
* 懒汉式
* @author Seven
*
*/
public class SingleDemo {

/**
* 私有化构造函数
*/
private SingleDemo(){

}

private static SingleDemo singleDemo = null;

/**
* 提供获取实例的方法,用synchronized来解决多线程的问题.
* @return
*/
public static SingleDemo getInstance(){
//二次判断提高效率
if(singleDemo==null){
synchronized (SingleDemo.class) {
if(singleDemo==null){
singleDemo = new SingleDemo();
}
}
}
return singleDemo;
}

}
所以,利用synchronized关键字解决多线程问题,用二次判断提高效率~

为什么用同步锁 
因为在项目中如果有很大的并发量的情况下,有可能造成同时又多个程序执行这个类实例化的方法,因此我们需要在创建类实例化方法的时候添加同步执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息