java中的线程安全(Threadsafe)及其四种策略

1.    线程安全:

    线程之间存在“竞争条件”,作用于同一个mutable数据上的多个线程,彼此之间存在对该数据的访问竞争并导致interleaving,导致post-condition可能被违反,这是不安全的。

    线程安全:ADT或方法在多线程中要执行正确。

    要做到:不违反spec,保持RI。与多少处理器,如何调度线程无关,不需要在spec中强制要求client满足某种“线程安全”的义务。

例如:Iterator就不是线程安全的,因为你不能在迭代遍历的时候改变collection。

保证线程安全,有四种策略:

(1)限制数据共享(Confinement)

(2)共享不可变数据(Immutability)

(3)共享线程安全的可变数据(Threadsafe data type)

(4)同步机制(Synchronization)

下面依次进行介绍:


2.     Confinement-限制数据共享

将可变数据限制在单一线程内部,避免竞争。

不允许任何线程直接读写该数据。

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

避免全局变量:例如我们之前的单例模式(Singleton Design Pattern)就存在风险:

java中的线程安全(Threadsafe)及其四种策略_第1张图片

3.     Immutability:

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

    关于不可变的更强定义:

    (1)无mutator方法

    (2)所有属性均为private和final的

    (3)没有表示泄露

    (4)表示中没有对可变类型的变化,甚至有益的变化也不允许

    不允许子类重写方法:最简单的做法实在类前加上关键final

4.      Using Threadsafe Data Types:

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

        在JDK中的类,文档中明确指明了是否threadsafe

        一般来说, JDK同时提供两个相同功能的类,一个是threadsafe,另一个不是。 原因:threadsafe的类一般性能上受影响 。

        集合类都是线程不安全的。

        因此Java API提供了进一步的decorator:

        

        进行包装(Wrap)

        java中的线程安全(Threadsafe)及其四种策略_第2张图片

    要注意的是:

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

    即使在线程安全的集合类上,使用iterator也是不安全的,除非使用lock机制(后续介绍)。

5.    Locks and Synchronization:

    同步与锁,最复杂也最具有价值的threadsafe策略。

    前三种策略的核心思想:

    避免共享->即使共享,也只能读/不可写(immutable)->即使可写,共享的可写数据

    也应自己具备在多线程之间协调的能力,即使用线程安全的mutable ADT。

    而很多时候,无法满足上述三个条件。

    因此采用同步与锁策略:

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

    一个锁就是一个线程在一个时间段对数据的占用。使用锁机制,获得对数据的独家mutation权,其他线程被阻塞,不得访问。

    lock的两个操作:

    获得与释放。

    java中的线程安全(Threadsafe)及其四种策略_第3张图片

可以使用synchronized方法,或在方法中加入代码块:

java中的线程安全(Threadsafe)及其四种策略_第4张图片

java中的线程安全(Threadsafe)及其四种策略_第5张图片

后者需要显式的给出lock,且不一定非要是this,能提供更加精细的lock粒度。

任何共享的mutable变量/对象必须被lock保护

涉及到多个mutable变量的时候,必须被同一个lock所保护。


同步机制给性能带来很大影响,除非必要,否则不要用。Java中很多mutable 的类型都不是threadsafe就是这个原因。

尽可能减小lock的范围。

线程安全的声明:

Concurrency argument:

    threadsafe by monitor pattern:all accesses to rep are guarded by this object's lock。











你可能感兴趣的:(java中的线程安全(Threadsafe)及其四种策略)