发布
对象的发布是指:使对象能够在当前作用域之外的代码中使用。例如在一个非私有的方法中将私有属性的对象引用直接返回。
逸出
是指当某个不该被发布的对象被发布出去。例如,如果在对象完成构造之前就将其发布出去,就会破坏线程安全性。
警惕this引用逸出。当从对象的构造函数中发布对象的时候,只是发布了一个未构造完成的对象。在构造过程中使用this引用逸出的一个常见的现象是:在构造函数中启动一个线程,无论是显式创建(将它传递给构造函数)还是隐式创建(由于Thread或者Runable是该对象的一个内部类),this引用都会被新创建的线程共享。对应this应用逸出的方法是,将构造函数声明为私有,同时提供一个工厂方法提供对象,在工厂方法中完成构造并且发布。
安全发布的常用模式
要安全的发布一个对象,对象的引用及对象的状态必须同时对其他线程可见
- 在静态初始化函数中初始化一个对象的引用(由于静态初始化器由JVM在类的初始化阶段机型,由于JVM内部存在同步机制,因此通过此方式初始化的任何对象都可以被安全的发布)。
- 将对象的引用保存在volatile类型域或者AtomReference对象中。
- 将对象的引用保存到某个正确构造对象的final类型域中。
- 将对象的引用保存到一个由锁保护的域中(比如Vector或者synchronizedList之类的线程安全的容器)。