62,614
社区成员
发帖
与我相关
我的任务
分享
public static Singleton getInstance()
{
if (instance == null)//4
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
这段代码 中,一个线程看到第四步 发现 不为null,拿去使用了。但是实际是这个不为null的对象,并没有完全实例化。
原因在于: 3处
这个地方代码只有一行,真正意义上完成一个对象需要三步。
1,分配对象的内存空间 1买了房子
2,为该对象的属性赋值 2给房子装修
3,初始化该对象。 3 把名字给你。
这个顺序不一定,加入说 3 执行了 再执行2 就出问题了.
解决办法是 给instance的修饰加上volatile 。这上这个字后 保证不会重排序。。。。这样得到的就是正确的对象。
回答完毕。
public static Singleton getInstance()
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
return instance;
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
个人认为问题不是出现在释放锁 而是博主说的代码优化
就是在创建对象的时候可能会存在1分配内存2创建引用关系3初始化对象 这样的优化创建方式
这样在//3处可能尚未完全创建对象时即2创建引用关系时由于CPU调度当前线程失去CPU
这时在最外层的 if (instance == null)处(非//2处)条件判断失败其他线程会直接返回instance 而此时线程1并未失去锁
另外,据说jdk1.5以后此问题已经被优化了。。。但是。。不太肯定。。。public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
先检查instance是否为null,如果为null则创建新实例。这时锁定Singleton.class。锁定进去了之后,再检查一下instance是否为null,就怕刚才有人已经把instance创建好了。
锁定前后各检查一次,就叫双重检查。