关于发布和逸出

并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了。这是危及到线程安全的,因为其他线程有可能通过这个逸出的引用访问到“初始化了一半”的对象(partially-constructed object)。这样就会出现某些线程中看到该对象的状态是没初始化完的状态,而在另外一些线程看到的却是已经初始化完的状态,这种不一致性是不确定的,程序也会因此而产生一些无法预知的并发错误。在说明并发编程中如何避免this引用逸出之前,我们先看看一个对象是如何产生this引用逸出的。

 
一、this引用逸出是如何产生的
     正如代码清单1所示,ThisEscape在构造函数中引入了一个内部类EventListener,而内部类会自动的持有其外部类(这里是ThisEscape)的this引用。source.registerListener会将内部类发布出去,从而ThisEscape.this引用也随着内部类被发布了出去。但此时ThisEscape对象还没有构造完成 —— id已被赋值为1,但name还没被赋值,仍然为null。
          
     代码清单1 this引用逸出示例

public class ThisEscape {

      public final int id;

      public final String name;

      public ThisEscape(EventSource<EventListener> source) {

            id = ;

            source.registerListener(new EventListener() {

                  public void onEvent(Object obj) {

                        System.out.println("id: "+ThisEscape.this.id);

                        System.out.println("name: "+ThisEscape.this.name);

                  }

            });

            name = "xingpc";

      }

  }

二、如何避免this引用逸出        上文演示了由内部类导致的this引用逸出是怎样产生的。它需要满足两个条件:一个是在构造函数中创建内部类(EventListener),另一个是在构造函数中就把这个内部类给发布了出去(source.registerListener)。因此,我们要防止这一类this引用逸出的方法就是避免让这两个条件同时出现。也就是说,如果要在构造函数中创建内部类,那么就不能在构造函数中把他发布了,应该在构造函数外发布,即等构造函数执行完毕,初始化工作已全部完成,再发布内部类。

public class ThisSafe {

      public final int id;

      public final String name;

      private final EventListener listener;

      private ThisSafe() {

            id = ;

            listener = new EventListener(){

                  public void onEvent(Object obj) {

                        System.out.println("id: "+ThisSafe.this.id);

                        System.out.println("name: "+ThisSafe.this.name);

                  }

            };

            name = "flysqrlboy";

      }

      public static ThisSafe getInstance(EventSource<EventListener> source) {

            ThisSafe safe = new ThisSafe();

            source.registerListener(safe.listener);

            return safe;

      }

}
 
 

Java并发编程实战 读书笔记(二)的更多相关文章

  1. Java并发编程实战 读书笔记(一)

    最近在看多线程经典书籍Java并发变成实战,很多概念有疑惑,虽然工作中很少用到多线程,但觉得还是自己太弱了.加油.记一些随笔.下面简单介绍一下线程. 一  线程与进程   进程与线程的解释   个人觉 ...

  2. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  3. 《java并发编程实战》笔记

    <java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为:  Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...

  4. Java多线程编程实战读书笔记(一)

    多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.

  5. 《Java并发编程实战》笔记-非阻塞算法

    如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败和挂起,那么这种算法就被称为非阻塞算法.如果在算法的每个步骤中都存在某个线程能够执行下去,那么这种算法也被称为无锁(Lock-Free)算法 ...

  6. Java并发编程实践读书笔记(5) 线程池的使用

    Executor与Task的耦合性 1,除非线程池很非常大,否则一个Task不要依赖同一个线程服务中的另外一个Task,因为这样容易造成死锁: 2,线程的执行是并行的,所以在设计Task的时候要考虑到 ...

  7. Java并发编程艺术读书笔记

    1.多线程在CPU切换过程中,由于需要保存线程之前状态和加载新线程状态,成为上下文切换,上下文切换会造成消耗系统内存.所以,可合理控制线程数量. 如何控制: (1)使用ps -ef|grep appn ...

  8. Java并发编程实践(读书笔记) 任务执行(未完)

    任务的定义 大多数并发程序都是围绕任务进行管理的.任务就是抽象和离散的工作单元.   任务的执行策略 1.顺序的执行任务 这种策略的特点是一般只有按顺序处理到来的任务.一次只能处理一个任务,后来其它任 ...

  9. Java并发编程实践读书笔记(2)多线程基础组件

    同步容器 同步容器是指那些对所有的操作都进行加锁(synchronize)的容器.比如Vector.HashTable和Collections.synchronizedXXX返回系列对象: 可以看到, ...

随机推荐

  1. HTML5 FormData 模拟表单控件 支持异步上传二进制文件 移动端

    FormData是XMLHttpRequest Level 2添加的一个新的接口,利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,还可以使用XMLHttpR ...

  2. 【Java_基础】java中的常量池

    1.java常量池的介绍 java中的常量池,通常指的是运行时常量池,它是方法区的一部分,一个jvm实例只有一个运行常量池,各线程间共享该运行常量池. java常量池简介:java常量池中保存了一份在 ...

  3. GIMP暗黑诱惑,部分彩色效果制作

    在一些图形处理中经常会用到高逼格的部分彩色,其他部分黑白的效果,今天我就简单记录一下如何操作. 1.选区,先选择要突出的选区,可以用多种方法,钢笔,套绳,小剪刀等等: 2.把选择的区域稍稍调整亮一点: ...

  4. js的弹性运动

    弹性: 速度+=(目标点-当前值)/系数://系数大概可以选择6,7,8 速度*=摩擦系数://系数可以选择0.7,0.75,0.8 缓冲: 速度=(目标点-当前值)/系数: 速度取整:

  5. 【php】子类覆盖超类方法,在超类里调用此方法会出现何种现象

    <?php class A { public function getName() { echo $this->name(); } function name () { return 'l ...

  6. auth认证组件

    Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...

  7. shell中test的使用

    #/secondin/secondfirstshecho “please enter two numseconder”read firstread secondif test $first -eq $ ...

  8. C++ STL容器底层机制

    1.vector容器 vector的数据安排以及操作方式,与array非常相似.两者的唯一区别在于空间的运用的灵活性.array是静态空间,一旦配置了就不能改变.vector是动态空间,随着元素的加入 ...

  9. UIDatePicker 显示时间和打印时间不一样

    默认是时区为0,如下格式化一下就好啦 UIDatePicker *datePiker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 100, ...

  10. Virtualbox虚拟机相关

    Virtualbox虚拟机相关 Virtualbox是我一直使用的虚拟机,由于需要一些测试环境等,会经常使用多个虚拟机.经常捣腾.之前有涉及到一些virtualbox方面的问题的处理,并没有记录下来, ...