饿汉式线程不安全及调试问题
代码
这里我们新建一个懒汉式单例:
public class LazySingleton {
//私有构造方法
private static LazySingleton instance;
private LazySingleton() {};
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
线程类:
public class ExectorThread implements Runnable {
public void run() {
LazySingleton instance = LazySingleton.getInstance();
System.out.println(Thread.currentThread().getName() + ":" + instance);
}
}
测试类:
import thread.ExectorThread;
public class LazySingletonTest {
public static void main(String[] args) {
Thread thread1 = new Thread(new ExectorThread());
Thread thread2 = new Thread(new ExectorThread());
thread1.start();
thread2.start();
System.out.println("end");
}
}
多线程调试
多线程的调试,在打断点的地方右键。然后在Suspend的地方勾选上Thread,这样就可以进行多线程的调试了。
在debug模式下,Frames里,可以看到你的多个线程的运行状态,点击线程,可以进行切换。
为什么懒汉式线程不安全
我们启动测试。多次运行后发现,会出现两种情况:
图一:
图二:
一种是同一个实例(图二),一种是两种实例(图一)。
分析一下,两种结果的情况:
同一种实例:
按照顺序执行,线程1执行完成后,线程2开始执行,线程2在if时,已经生成了实例,所以不会执行实例化的过程。结果只有一个。
产生了覆盖的情况,线程1在进入if语句块后,线程2也进入了语句块,先后完成了实例化,不过线程2覆盖了线程1的实例。然后各自走出if语句,导致在输出时,指向的是同一个实例,输出的地址值一样。
两个实例:
线程1和线程2都进了if语句,线程1完成了实例化,并打印了结果,线程2也进行了实例化,然后打印自己的结果,这样就会产生两个单例。
分析完成后,再验证一下自己的猜想。通过上面的多线程调试的方式。
总结
单例模式的定义是在任何条件下,都只会产生一个实例,很明显,在多线程的情况下,违背了单例的定义,所以说懒汉式单例线程不安全。