Java并发编程实战-可爱猪猪解读

对象发布与逃逸-this逃逸

2017-09-16  本文已影响274人  兰塔项

what is this escape?

在《Java Concurrency in Practice》一书的第三章提到了对象的发布与逃逸。作者举了this指针逃逸的例子。所谓的“this逃逸”,指的是在构造函数返回之前,其他线程就已经取得了该对象的引用。此时,对象尚未完成实例化,还是残缺的,取得对象引用的线程使用残缺的对象可能引发令人遗憾的错误。作者举的例子,不太容易理解,下面对该例子做适当扩展来理解“this逃逸”。

show me the code

我在com.gongjun.study.concurrency包下建了下面的三个类:

public class ThisEscape {

    private final int num;

    public ThisEscape(EventSource source) {
        source.registerListener(new EventListener() {
            public void onEvent(Object o) {
                doSomething(o);
            }
        });
        num = 42;
    }

    private void doSomething(Object o) {
        if (num != 42) {
            System.out.println("Race condition detected at " + new Date());
        }
    }
}
public class EventSource {

    public void registerListener(EventListener listener) {}

}
public interface EventListener {

    public void onEvent(Object o);
}

analysis the code

1.手动编译源代码,生成class文件

javac EventSource.java EventListener.java ThisEscape.java
image.png

我们看到对ThisEscape中的内部匿名类EventListener生成了对应的class文件ThisEscape$1.class

2.查看ThisEscape的字节码

javap -verbose ThisEscape.class
image.png

在ThisEscape的构造器中,new了一个匿名类ThisEscape$1,并将自己作为入参,即为我们所说的this引用。

3.查看匿名类ThisEscape$1的字节码

javap -verbose ThisEscape\$1.class
image.png

从字节码中,我们看到匿名类确实持有了外部类的引用。

由此,我们可以看出确实发生了对象(this)的逃逸,EventSource中的registerListener完全有可能在异步线程中执行,某种情况下ThisEscape还没完全构造完全,而在EventListener的匿名类中通过持有this引用,调用ThisEscape的doSomething方法,会出现不满足预期的结果。

reference

How Does "this" Escape?
深入JAVA002_对象的发布和逃逸 --this解惑

上一篇 下一篇

猜你喜欢

热点阅读