this逃逸问题

在学习并发编程的时候,大多数的资料都会涉及到this逃逸这个问题。

从本质上讲,this代表当前对象名,是一个指向本对象的指针。

 

首先看两个例子:

第一个:

public class ThisEscape {
    private final int var;

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


        // more initialization
        // ...
        var = 10;
    }


    // result can be 0 or 10
    int doSomething(Event e) {
        return var;
    }
}

事件监听器一旦注册成功,就能够监听用户的操作,调用对应的回调函数。也就是调用doSomething()这个方法。这个时候是异步的。而对象ThisEscape的构造函数还有可能没有执行完,此时并没有给var变量赋值(var = 0),所以此时doSomething中获取到的数据有可能是0,并不是10.


第二个:

public class ThreadThisEscape{
     private int weight = 0;

     public ThreadThisEscape(){
         weight = 1;

         new Thread(new EscapeRunnable()).start();

         // 构造函数比较耗时
     }

     private class EscapeRunnable implements Runnable{
          public void run(){
                  System.out.println(ThreadThisEscape.this.weight);
          }
     }

     public static void main(String[] args){
           new ThreadThisEscape();
     }
}

这种情况,在构造函数构造的过程中,可能出现指令重排序的问题,所以有可能先执行EscapeRunnable线程的启动,这个时候,访问到的weight也有可能是0.

总结一下:

对于对象的发布和逸出,有2中常见的情况:在构造函数中注册事件监听,在构造函数中启动新线程。代码如下:

第一种:在构造函数中注册事件监听:

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


第二种:在构造函数中启动新线程:

public class ThreadThisEscape {  
    public ThisEscape() {  
        new Thread(new EscapeRunnable()).start();  
        // ...  
    }  
      
    private class EscapeRunnable implements Runnable {  
        @Override  
        public void run() {  
            // ThreadThisEscape.this就可以引用外围类对象, 但是此时外围类对象可能还没有构造完成, 即发生了外围类的this引用的逃逸  
        }  
    }  

这2中方式的共同点是:在构造函数中使用内部类,并且代码可能会出现并行运行。也就是说,当内部类代码执行的时候,外部类对象的创建过程还有可能没有结束,这个

时候如果内部类访问外部类的数据,很有可能得到没有正确初始化的数据。


也就是说,this逃逸是说在构造函数返回之前其他线程就持有该对象的引用,调用尚未构造完全的对象的方法可能引发错误。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值