软件构造 线程安全 复习笔记

线程安全的四种策略总结

一、Confinement限制可变变量的共享

核心思想:线程之间不共享mutable数据类型

将可变数据限制在单一线程内部,避免竞争;不允许任何线程直接读写该数据

局部变量总是线程安全的,但如果局部变量是一个对象引用,若该对象是可变对象,则必须确定该对象也是线程confine 的,不能有其他线程也只想该对象的引用。

下面给出一个例子说明

在getInstance中,执行完第一行后执行第三和,java并不能保证在一个线程中对其对象做出的改变就对其他对象课件,他可能会被缓存下来,于是虽然第三和的线程已创建一个,但第一行的线程可能并不知道,就有可能创建两个对象。

二、Immutablity不可变数据类型

使用不可变数据类型和不可变引用,避免多线程之间的竞争

不可变数据类型通常是线程安全的,如果ADT使用了可变类型,需要通过加锁机制来保证线程安全。

更强的不变性定义如下:

1.没有改变数据的操作。(不要提供setter方法等)
2.所有字段均为private和final。
3.没有表示泄露。
4.表示中的任何可变对象都不能发生变化。
5.不允许子类重写方法(直接声明为final类,或者使构造方法私有,使用工厂方法构造实例)
但是注意:如果是引用,任然必须保证指向的对象是不可变的。

三、Using Threadsafe Data Types使用线程安全的数据类型

如果必须要使用mutable 的数据类型在多线程之间共享收据,要使用线性安全的数据类型

所有的集合类都不是线程安全的,Java提供了装饰器模式

在使用synchronizedMap(hashMap)之后,不要再把参数hashMpa共享给其他线程,不要保留别名,一定要彻底销毁。

即使在线程安全的集合类,使用iterator也是不安全的,除非使用lick机制,如下:

 仅仅是原子操作并不足以确保线程安全,原子操作的组合仍旧可以尝试race condition

四、locks and sychronization 

同步和锁:防止线程在同一时间访问同一数据

程序员之间负责多线程之间对mutale数据的共享操作,通过同步策略,避免多线程同时访问数据

使用锁机制。获得对数据的独家mutate权力。其他线程被阻塞,不能访问。

Monitor Pattern:用ADT之间左lock,对所有方法都加锁,把synchronized放到方法声明里和把方法体外套一个symchronized一样

Locking principle:任何共享的mutable变量必须被lock所保护  

                              设计到多个mutable变量的适合,他们必须被同一个lock保护

同步机制给性能带来很大的影响

死锁:多个线程相互竞争lock,相互等待对方释放lock

解决方案1:lock ordering

解决方案2:使用上级对象上锁

猜你喜欢

转载自www.cnblogs.com/boston-o/p/11074994.html
今日推荐