第四章 之地基

线程安全性的委托

Java中对象大多是组合对象,如果组合对象都已经是线程安全的,还需要给这些组合对象增加一层线程安全机制吗?答案:“视情况而定”!

三种委托方式:

  • 如果组合对象A的状态是由线程安全的对象B的状态构成的,那么A的线程安全就可以委托给B来保证。
  • 如果组合对象A的状态是由线程安全的对象B、C、D…的状态构成,想让A的状态委托给这些对象,需要这些对象是彼此独立的。即不用在A包含的多个状态上额外增加不变性条件
  • 如果组合对象A下的对象有着相互制约的条件,比如B和C都是线程安全的对象但是B要大于C,这时候需要A提供自己的线程安全机制以保证原子性操作。

发布底层的状态变量

能发布的前提:

  • 线程安全
  • 没有任何不变性条件来约束他的值
  • 对变量的操作上不存在任何不允许的状态转换

给现有的线程安全类中添加功能

  • 最安全的方法修改原始的类。
  • 继承这个类,但这样做很脆弱。并非所有类都像Vector装状态向子类公开,原有类一旦改变了安全策略,子类就会被破坏
// 拓展类示例
@ThreadSafe
public class BetterVector<E> extends Vector<E>{
	public synchronized boolean putIfAbsend(E x){
		boolean absent = !contains(x);
		if(absent)
			add(x);
		return absent;
	}
}
  • 客户端加锁,比继承类还脆弱,都会破坏同步策略的封装性。要使用某段代码需要使用这段代码本身的锁来保护,必须知道这段代码使用的是那个锁。要不然不足以支持线程安全!
//客户端加锁正确示例
@ThreadSafe
public class ListHelper<E>{
	public List<E> list = Collections.synchronizedList(new ArrayList<E>());
	public boolean putIfAbsent(E x){
		synchronized (list){
			boolean absent = !list.contains(x);
			if(absent)
				list.add(x);
			return absent;
		}
	}
}

//客户端加锁错误示例,因没有使用对象本身的锁进行保护
@NotThreadSafe
public class ListHelper<E>{
	public List<E> list = Collections.synchronizedList(new ArrayList<E>());
	public synchronized boolean putIfAbsent(E x){
		boolean absent = !list.contains(x);
		if(absent)
			list.add(x);
		return absent;
	}
}
  • 组合,新类将原有的对象作为域,加入新的方法并用自己的锁对所有方法进行保护,使用了java的监视器模式来实现的。更为健壮,不用去管原有类是否是线程安全,都会由新类提供一致的加锁机制。
@ThreadSafe
public class ImprovedList<T> implements List<T>{
	private final List<T> list;
	public ImprovedList(List<T> list){
		this.list = list;
	}
	public synchronized boolean putIfAbsent(T x){
		boolean contains = list.contains(x);
		if(contains)
			list.add(x);
		return !contains;
	}
	//按照类似的方式委托list的其他方法
	public synchronized void clear(){
		list.clear();
	}
}

将同步策略文档化

在文档中要说明客户代码需要了解的线程安全保证,以及代码维护人员需要了解的同步策略。
了解含糊的同步策略,可以从开发者的角度去考虑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值