一 . 概要:
单例模式:
A. 一个类只能构建一个对象,自然不能让它随便去做new操作
B. 分为 懒汉模式 和 饿汉模式
C. 考虑到 线程安全
网上看别人写的单例模式很多,多数都没有考虑到线程安全的例子。
在此,总结一下,第三版 是线程安全的。重点讲解 第三版代码。
二. 封装列举
首先
public class A{
private A() {} //私有构造函数
private static A instance = null; //单例对象
//静态工厂方法
public static A getInstance() {
if (instance == null) {
instance = new A();
}
return instance;
}
}
这就是一个单例,但是有不足的地方很多。
第一,这样写 是没有错的。可以运行,也符合,只创建一个对象。确实是单例,这是懒汉式,要想饿汉式,那就开始时候new
private static A instance = new A();
但是,问题来了,。。。。。要是多线程时候呢,线程A 和 线程B 同时执行到 if(instance) 这个时候,instance是null 都进入 if 语句
那么就有 new 两次,多个对象,显然又不符合单例模式。。。单例单例,就是只有一个。。。那么我们继续往下看第二版本
然后
public class A{
private A() {} //私有构造函数
private static A instance = null; //单例对象
//静态工厂方法
public static A getInstance() {
if (instance == null) { //双重检测机制
synchronized (A.class){ //同步锁
if (instance == null) { //双重检测机制
instance = new A();
}
}
}
return instance;
}
}
这个比前面的好一些了,双重检查机制 又判空 null 又加锁,这回多个线程访问是问题的。
可以防止 new A() 执行多次
总体看是可以的,但是还不是绝对线程安全
假如 : 要么Instance还没被线程A构建,线程B执行 if(instance == null)的时候得到true;要么Instance已经被线程A构建完成,线程B执行 if(instance == null)的时候得到false。
真的如此吗?答案是否定的。这里涉及到了JVM编译器的指令重排。
指令重排,这个东西有点难讲解,实力不足。。。大神多指点。。。
需要增加 volatile 关键字 线程安全用
最后
public class A{
private A() {} //私有构造函数
private volatile static Ainstance = null; //单例对象
//静态工厂方法
public static A getInstance() {
if (instance == null) { //双重检测机制
synchronized (A.class){ //同步锁
if (instance == null) { //双重检测机制
instance = new A();
}
}
}
return instance;
}
}
注意看代码 第三行。第三行。第三行。
这回,线程够安全了,volatile这个字在百度百科说
简单地说就是防止编译器对代码进行优化。比如如下程序:
精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。 以上是百度百科的说法。。。 结束,,,,,感谢小灰灰, 让我知道有volatile这个关键字,分享出来,给大家。XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;