第二章 线程安全性
2.1 什么是线程安全性
当多个线程访问某个类,这个类始终表现出正确的行为,称这个类是线程安全的。
线程安全类:无状态类
完全由线程安全类组成的程序不一定是线程安全的,线程安全类中也可以包含非线程安全的类。
2.2 原子性
一系列操作不可分。
2.2.1 竞态条件
不恰当的执行顺序出现不正确的结果,这一情况称为竞态条件。
类型之一:先检查后执行。大多数的竞态条件出现的原因是出于可能失效的观察结果作出决定。
2.2.3 复合操作
将全部的复合操作交由线程安全对象执行保证安全性。
延伸:无状态类中添加一个线程安全成员对象,仍然是线程安全的。
2.3 加锁机制
不变性条件涉及多个变量,仅保证每个变量都是线程安全对象是无用的。需要将对所有变量的操作封装在一个原子操作中。
2.3.1 内置锁
java提供了同步代码块保证范围加锁。同步代码块由两部分组成:加锁的对象和加锁区间
synchronized(lock){ //线程安全操作区间 }
每个java对象都可以当成锁(对象头中的锁状态标识)。这种锁称为内置锁,获取锁的线程进入代码块,退出代码块释放锁。
用同一个对象当锁锁住多个代码块,统一时间只能获取其中一个的访问权限。
//锁对象 private Object lock; synchronized(lock){ //代码A } synchronized(lock){ //代码B }
2.3.2 重入
内置锁可以重入。子类改写父类的同步方法,两者是一个锁管理。
2.4 锁保护状态
锁保护状态的更改和读取,保证访问的串行。(指广义的锁概念)
2.5 活跃性和性能
加锁限制并发性,只在必要情况和范围内加锁,细心维护加锁的粒度。
人生就像蒲公英,看似自由,其实身不由己。