线程安全性

1、什么是线程安全性

从一开始就设计一个线程安全的类,比在以后再将这个类修改为线程安全的类要容易的多。

线程安全的类中封装了必要的同步机制,因此客户端无需进一步采取同步措施。

无状态对象一定是线程安全的(不包含任何域和其他类的引用,只有线程局部变量)

2、原子性

int类型也非原子,++count包含了读取,修改,写入的操作序列。

2.1、竞态条件

UnsafeCountingFactorizer

最常见的竞态条件类型是:先检查后执行操作,即通过一个可能失效的观测结果来决定下一步的动作。

2.2、示例:惰性初始化中的竞态条件

LazyInitRace

单利模式的懒惰模式如果没有加同步,多线程可能产生不同的对象实例

2.3、复合操作

要避免竞态条件问题,就必须在某个线程修改该变量时,通过某种方式防止其他线程使用这个变量,也就是让其变成原子操作(两个线程互斥)

在实际情况中,应该尽可能使用现有线程安全对象如AtomicLong来管理类的状态。

3、加锁机制

为了保护状态的一致性,要在单一的原子操作中更新相互关联的状态变量。

3.1、内置锁

synchronized块,是互斥锁(mutual exclusion lock,也称作mutex)。

3.2、重入(Reentrancy)

内置锁是可重入的,防止一下这种情况导致的死锁:

重入锁的请求是基于每个线程的,而不是每个调用;通过为每个锁关联一个请求计数和一个占有它的线程实现的。

4、用锁来保护状态

如果用同步来协调访问变量,每次访问变量时,都需要同步,每次访问变量都需要同一个锁。

5、活跃性与性能