Crab213's Blog.

Java并发编程实践笔记3:构建对象

2016/03/31

我们不可能总是从头设计自己的程序,java语言本身提供了许多模块来帮助我们构建线程安全的多线程程序。

设计一个线程安全的类

使用封装可以简化我们的工作,依靠良好的封装,我们可以更简单地确定一个类是否线程安全,或更更改一个线程安全的类。设计一个线程安全的类一般分为三步:

  1. 找出那些组成这个类状态的变量
  2. 找出那些约束状态变量的不变式
  3. 建立一种管理并发操作对象状态的机制

我们必须注意约束这个类的状态的不变式,一切同步行为都是以不变式为准。如果对一个变量的操作会违反不变式,造成类进入一个非法的状态,我们就应该将这个操作封装起来然后加以同步。如果不了结一个对象的不变式,那么你就无法保证线程安全。对状态或者状态转移的约束会需要而外的原子操作和封装。

实例封闭(instance confinement)

实例封闭与线程封闭一样,都是一种让非线程安全的对象变得线程安全的方法。线程封闭将对象的使用限制在一个线程中,而对象封闭将一个对象的使用限制在另一个对象中,再将外层对象的方法用锁同步。

Java Monitor模式是java中常见的模式,它是实例封闭的一种实现,Collections类中以synchronized打头的方法都是使用了该模式。它们返回了一个新的将原先方法同步过了的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class OuterClass {
private final Object mutex;
private final InnerClass inner;

public OuterClass(InnerClass c) {
this(c, this);
}

public OuterClass(InnerClass c, Object mutex) {
inner = c;
this.mutex = mutex;
}
}

委托线程安全(delegating thread safety)

对象封闭是将本来不适线程安全的对象包装得线程安全。但是本来就线程安全的对象,我们可以采取另一种方式将其合成为新的对象。如果一个类由几个独立的线程安全的状态变量合成,并且没有会转移到非法状态的操作,那么它可以将线程安全委派给组成它的线程安全状态变量。

如果一个线程安全的变量没有被任何不变式约束,也没有被禁止更改其状态,那么它是可以被安全发布的。

CATALOG
  1. 1. 设计一个线程安全的类
  2. 2. 实例封闭(instance confinement)
  3. 3. 委托线程安全(delegating thread safety)