10.2Thread Safety线程安全

10.2Thread Safety

0.Thread safety

1.Strategy 1: Confinement 限制共享

2.Strategy 2: Immutability 共享不变量

3.Strategy 3: Using Threadsafe Data Types 用线程安全数据类型

4.Strategy 4: Locks and Synchronization 线程锁

5.How to Make a Safety Argument 怎么说明安全

 

 

 

0.线程安全

线程竞争导致Post condition可能违反。

线程安全指ADT或方法在多线程中要执行正确。(不违反spec和RI)

Itreator是线程不安全的,remove()也是不安全的,在Java doc有说明

4种保证threadsafety的方法:

1.限制共享数据(不和其他线程共享数据)

2.共享不可变数据(保持数据是immutable的)

3.共享线程安全的可变数据(保证数据的操作是线程安全的)

4.同步机制:通过锁的机制共享线程不安全的可变数据,变并行为串行(线程锁)

 

1.Confinement 限制数据共享

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

 

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

 

!!:之前为了优化,而设计的Singleton 设计模式会导致创建对象时发生竞争,可能创建两次对象,导致 线程不安全

 

 

 

避免使用全局变量,如果可以也别使用静态变量(所有调用此静态变量的方法,如果被多个线程调用多次,是会发生竞争的)

如果一个 ADT 的 rep 中包含mutable 的属性且多线程之间对其进行 mutator 操作,那么就很难使用 confinement 策略来确保该 ADT是线程安全的

 

2.Immutability 保持数据不变

使用不可变数据类型和不可变引用,通常避免多线程之间的竞争情况(数据只读)

PS:beneficent mutation为特殊情况,这时可能竞争

 

为了保证线程安全,我们强定义immutability:

--不准有mutator  ---没有setter

--所有属性都是private and final

--No rep exposure

--什么情况也不允许mutation(包括beneficent mutation,保证子类安全,不允许override)

对于数据的引用采用防御性拷贝

 

 

3.Using Threadsafe DataTypes 用线程安全数据类型

如果必须要用 mutable 的数据类型在多线程之间共享数据,要使用线程安全的数据类型。(Threadsafe 的数据类型,JAVA文档中明确指出,通常保证线程安全会影响性能)

集合类(Set,Map,List)都是不安全的,JAVA API 提供decorator模式保证这些集合类线程安全(synchronized+集合类的类型)

 

最好不保留别名,不把hashMap共享给其他线程

PS!!!:即使线程安全的集合类依然可能线程不安全(1.遍历或iterator;2.使用多个操作)

 

如左图,当第一行语句结束后可能其他线程调用remove(),依然不安全

 

PS:所有数组都是线程不安全的

 

 

总结一下:1.最好不共享数据 2.共享不变的数据 3.共享线程安全的数据

 

4.How to make a safety argument 用线程安全数据类型

Spec:对线程安全说明

Test:测试线程安全的状况

Rep:写好AF,RI,checkRep

Thread Safety Arguments:显式说明保证线程安全的决策,采取什么的方法保证安全

猜你喜欢

转载自blog.csdn.net/qq_42766619/article/details/90700423