对象的共享-安全发布

前面介绍,发布是指使对象能够在当前作用域之外的代码中使用。要正确的发布对象,需要保证对象的引用以及对象的状态对其他线程可见。

安全发布的常用模式

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

  1. 静态初始化对象的引用或者在静态代码块中初始化(静态初始化器的发布方式)。

    1
    public static Publishable publishable= new Publishable();

    1
    2
    3
    4
    public static Publishable
    static{
    publishable= new Publishable();
    }

    静态初始化器由JVM在类的初始化阶段执行。JVM内部存在同步机制,因此可以安全发布。

  2. 将对象的引用保存到volatile类型的域或者AtomicReference对象中。
  3. 将对象的引用保存到某个正确构造对象的final类型域中。
  4. 将对象的引用保存到锁保护的域中。

事实不可变对象(Effectively Immutable Object)

不可变对象在正确构建之后就不得进行修改。如果对象从技术上是可变的,但其状态在发布后不改变,就称为事实不可变对象。
可以这么理解,事实不可变对象对象中包含一个可变对象,但是并没有提供能改变可变对象的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Line {
private final Point start;
private final Point end;
public Line(final Point start, final Point end) {
this.start = new Point(start);
this.end = new Point(end);
}
public void draw() {
//...
}
public Point getStart() {
return new Point(start);
}
public Point getEnd() {
return new Point(end);
}
}

这里Point是可变的,但是Line并没有提供获得自身Point引用的方法,而是返回了新建的Point对象,所以Line是事实不可变对象。

为何使用事实不可变对象

可以简化开发过程,还可以减少同步而提高性能。

发布
不可变对象事实不可变对象
可以任意发布需要安全发布