Java并发编程之不变性与安全发布

2020-01-17 18:21:41 浏览数 (3)

1、不变性

如果某个对象在被创建后其状态就不能被修改,那么这个对象就被称为不可变对象。满足同步需求的另一种方法就是使用不可变对象。不可变对象一定是线程安全的。当满足以下条件时,对象才是不可变的:

  • 对象创建以后其状态就不能改变
  • 对象的所有域都是final类型
  • 对象是正确创建的,在对象创建期间,this引用没有泄露
2、final域

final类型的域是不能修改的,但如果final域所引用的对象是可变的,那么这些被引用的对象是可以修改的。final域的对象在构造函数中不会被重排序,所以final域也能保证初始化过程的安全性。和“除非需要更高的可见性,否则应将所有的域都声明为私用域”一样,“除非需要某个域是可变的,否则应将其声明为final域”也是一个良好的编程习惯

3、安全发布

到目前为止,我们重点讨论的是如何确保对象不被发布,例如让对象封闭在线程或另一个对象的内部。当然,在某些情况下我们希望在多个线程间共享对象,此时必须确保安全地进行共享。然而,如果只是像下面程序那样将对象引用保存到公有域中,那么还不足以安全地发布这个对象。

代码语言:javascript复制
    //不安全的发布      public User user;     public void initialize() {       user = new User(42);    }

     由于存在可见性问题,其他线程看到的User对象将处于不一致的状态,即便在该对象的构造函数中已经正确地构建了不变性条件。这种不正确的发布导致其他线程看到尚未创建完成的对象。

4、安全发布的常用模式

一个正确构造的对象可以通过以下方式来安全地发布:

  • 在静态初始化函数中初始化一个对象引用
  • 将对象的引用保存到volatile类型的域或者AtomicReferance对象中
  • 将对象的引用保存到某个正确构造对象的final类型域汇总
  • 将对象的引用保存到一个由锁保护的域中(例如Vector,synchronized List)

注:本文为Wayne原创,未经许可不得在任何平台转载。如需转载,与作者联系

0 人点赞