现在大家都知道“双重检查成例”在java是有问题的,现在不考虑这个问题,或者就当“双重检查成例”在java是没有问题的,但我现在又发现另一个问题,令我十分疑惑,这就是线程安全的问题,且看下面的经典代码:
public class LazySingleton {
private static LazySingleton m_instance;
private LazySingleton() {
} public  static  LazySingleton   getInstance() {
if (m_instance == null) {
synchronized(LazySingleton.class) {
if   (m_instance == null) {
m_instance = new LazySingleton();
}
}

return m_instance; 

} 如果有线程A在执行if (m_instance == null) {,而线程B在执行m_instance = new LazySingleton();,结果会怎样?
A在执行if (m_instance == null) {并不是在synchronized里的,这样是线程安全的吗?

解决方案 »

  1.   

    如果不考虑Out-of-order writes现象,那完全是线程安全的因为此时A线程判断无非两个结果:
    1.null 那就进入同步序列,等待B线程完成初始化,A然后取现成的
    2.非null 那直接取现成的关于Out-of-order writes现象,就是
    m_instance = new LazySingleton();
    m_instance已经非空,但对象还没完成实例化,即new LazySingleton()未完成
    详见:
    http://www.ibm.com/developerworks/java/library/j-dcl.html
      

  2.   

    按照这样说,那下面的代码线程安全吗?public class Globe {
    public Date date = null;
    }thread A:
    run () {
    while (true) {
    Date date1 = Globe.date;
    }
    }thread B:
    run() {
    while (ture) {
    Globe.date = new Date();
    }
    }date1总能得到一个正常的、而非意外的对象吗?我想知道的就是java在对象的赋值和访问是否原子化的?谢谢
      

  3.   

    写错了public class Globe {
        public static Date date = null;
    }
      

  4.   

    Java里的引用
    其实就是个int类型的地址。
    多线程的存取应该是原子的
    也就是是说,你获取的引用总是一个有效的引用。
    否则不是发生内存紊乱了么
      

  5.   

    你这例子哪里是取呢?读的话关乎可见性问题,读总是原子的吧
    写存在原子性问题,java对象赋值在某些情况下不是原子的,就是所谓的Out-of-order writes现象
      

  6.   

    线程A里
    Date date1 = Globe.date;
    这里取