前面讲了保证线程安全的两种思路:安全的共享(保证同步)和线程封闭(不共享也就不存在线程安全的问题)。还有一种思路是共享只读的数据(不可更改当然没有一致性的问题)。并发编程书中强调了不可变对象一定是线程安全的。
不可变对象需要满足的条件:
- 对象创建后状态不可更改
- 对象的所有域都是final类型(如果所有域不会逸出的话,也可以不是final,但是保险起见)
- 对象在创建期间没有逸出
//并发编程书中一个不可变对象的例子
public class FinalClass {
private final Set<String> stooges = new HashSet<String>();
public FinalClass() {
stooges.add("one");
stooges.add("two");
stooges.add("three");
}
public boolean isStooge(String name){
return stooges.contains(name);
}
}
总结
并发程序中使用和共享对象时的策略:
- 线程封闭:线程封闭的对象只能由一个线程拥有,对象封闭在该线程中,并且只能由这个线程共享,例如:使用栈封闭,ThreadLocal类
- 只读共享:使用不可变的对象,多个线程可以共享访问,但是都不能改变它。
- 线程安全共享:使用volatile,synchronized设计类
- 保护对象:将需要线程安全的对象封装在其他对象中,使用内部对象的数据时必须获得外部对象的锁。