单例模式中可能存在的⼀些问题(线程安全问题)
单例的设计模式中,⼀些代码的写法会存在线程安全的问题,举例如下:
(1)单例模式的懒汉式[线程不安全,不可⽤]
public class Singleton {
private static Singleton instance=null;
private Singleton() {};
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
这种⽅式是在调⽤getInstance⽅法的时候才创建对象的,所以它就被称为懒汉模式。
这是存在线程安全问题的,那具体是存在怎样的线程安全问题?怎样导致这种问题的?好,我们来说⼀下什么情况下这种写法会有问题。在运⾏过程中可能存在这么⼀种情况:多个线程去调⽤getInstance⽅法来获取Singleton的实例,那么就有可能发⽣这样⼀种情况,当第⼀个线程在执⾏if(instance==null)时,此时instance是为null的进⼊语句。在还没有执⾏instance=new Singleton()时(此时instance是为null 的)第⼆个线程也进⼊了if(instance==null)这个语句,因为之前进⼊这个语句的线程中还没有执⾏instance=new Singleton(),所以它会执⾏instance = new Singleton()来实例化Singleton对象,因为第⼆个线程也进⼊了if语句所以它会实例化Singleton对象。这样就导致了实例化了两个Singleton对象。所以单例模式的懒汉式是存在线程安全的,既然它存在问题,那么可能有解决办法,于是就有下⾯加锁这种写法。
(2)懒汉式线程安全的[线程安全,效率低不推荐使⽤]
public class Singleton {
private static Singleton instance=null;
private Singleton() {};
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
缺点:效率太低了,每个线程在想获得类的实例的时候,执⾏getInstance()⽅法都要进⾏同步。⽽其实这个⽅法只执⾏⼀次实例化代码就够了,后⾯想获得该实例,直接return就⾏了。⽅法进⾏同步效率太低要改进。
(3)单例模式懒汉式[线程不安全,不可⽤]
public class Singleton7 {
private static Singleton instance=null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
}
这种写法也是不安全的,当⼀个线程还没有实例化Singleton时另⼀个线程执⾏到if(instance == null)这个判断时语句机会进⼊if语句,虽然加了锁,但是等到第⼀个线程执⾏完instance=new Singleton()跳出这个锁时,另⼀个进⼊if语句的线程同样会实例化另外⼀个SIngleton对象。因为这种改进⽅法不可⾏。
(4)单例模式懒汉式[线程安全,可⽤]
public class Singleton7 {
private static Singleton instance=null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
java单例模式懒汉和饿汉if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
(5)单例模式饿汉式[线程安全,可⽤]
public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
//静态⼯⼚⽅法
public static Singleton1 getInstance() {
return single;
}
}
饿汉式在类创建的同时就已经创建好⼀个静态的对象供系统使⽤,以后不再改变,所以天⽣是线程安全的。
(6)单例模式的成员变量[线程不安全,不可⽤]
public class Singleton {
int i =0;
private Singleton() {}
private static final Singleton1 single = new Singleton1();
//静态⼯⼚⽅法
public static Singleton1 getInstance() {
i++;
return single;
}
}
这种写法也是不安全的,当⼀个线程还没有执⾏到i++时另⼀个线程执⾏到int i=0,导致i=1⽽不是2,应改为局部变量写法较好总结:
以上就是单例模式中,会引发的线程安全问题了

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。