Java多线程 隐式地允许this引用逸出

今天看Java并发编程看到这一段:

public class ThisEscape {
    
    public ThisEscape(EventSource source) {
        source.registerListener(new EventListener(){
            public void onEvent(Event e) {
                doSomething(e);
            }
        } );
    }

    private void doSomething(Event e) { }


    interface EventSource {
        void registerListener(EventListener e);
    }

    interface EventListener {
        void onEvent(Event e);
    }

    interface Event {
    }

}

这样子是不允许,叫做隐式地允许this引用逸出,感觉看书里的解释很迷。
以下是我个人的看法:
为什么这个是线程不安全的,我个人理解就是因为这个匿名内部类的创建过程出现的问题。我们在构造器中传入EventSource的对象引用,这时,我们往EventSource注册了一个监听器对象,可是我们都知道new本来就不是原子操作,它
是分为三步的:

  • 分配内存空间
  • 初始化对象
  • 将对象指向刚分配的内存空间变成了
    由于jvm优化发生指令重排:
  • 分配内存空间
  • 将对象指向刚分配的内存空间
  • 初始化对象
    当我们执行到第二步的时候刚好有其他的线程在访问这个EventSource对象(我们传入的),这时候我们已经能够取到刚注册的监听器对象(逸出),但是由于他并不处于稳定状态,因为没有初始化完毕,那么该线程就会抛出异常,这个过程和双重检验锁的过程其实是类似的,
    因为匿名内部类我们并不能保证其可见性,所以导致了对象创建不完全就被其他线程直接访问抛出异常。
    这就是我对这个概念的理解,有问题的可以探讨一下,可能我的观点错了。

posted on 2018-10-15 14:20  小新动感光波  阅读(763)  评论(1编辑  收藏  举报

导航