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对象(我们传入的),这时候我们已经能够取到刚注册的监听器对象(逸出),但是由于他并不处于稳定状态,因为没有初始化完毕,那么该线程就会抛出异常,这个过程和双重检验锁的过程其实是类似的,
因为匿名内部类我们并不能保证其可见性
,所以导致了对象创建不完全就被其他线程直接访问抛出异常。
这就是我对这个概念的理解,有问题的可以探讨一下,可能我的观点错了。