作者: 康凯森
日期: 2016-11-05
分类: Java
线程安全的核心在于对状态访问
进行管理,特别是对共享的
和可变的
状态进行访问。 换句话说,对于不可变或者不共享的状态进行访问就不会存在线程安全性问题。
共享
意味着变量可以由多个线程访问。
可变
意味着变量的值在其生命周期可能发生变化。
无状态对象一定是线程安全的
。
当在无状态的类中添加一个状态时,如果该状态完全由线程安全的对象来管理
,那么这个类仍然是线程安全的。
要保持状态的一致性,就需要在单个原子操作
中更新所有
相关的状态变量。
当多个线程
访问某个类时,不管运行时环境采用何种调度方式
或者这些线程将如何交替执行
,并且在主调代码中不需要任何额外的同步或协同
,这个类始终
可以表现出正确的行为,则称这个类是线程安全的。
即不可分割的操作
,这些操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
并发环境的原子性和是事务应用程序的原子性有着相同的含义—— 一组语句作为一个不可分割的单元被执行。
竞态条件: 不恰当的执行顺序会出现不正确的结果
。
当多个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。
大多数竞态条件的本质——基于一种可能失效的观察结果
来做出判断或执行某个计算,这种类型的静态条件称为“先检查后执行”。
每个Java对象都可以用作一个实现同步的锁,这些锁称为内置锁
或者监视器锁
。
synchronized(lock) {
//访问或者修改由锁保护的共享状态
}
重入: 一个线程
可以再次
获得一个已经由它自己持有
的锁。
重入的一种实现方式:
对于可能被多个线程同时访问
的可变
状态变量,在访问它时都需要持有同一个锁
,在这种情况下,我们称这个变量是由这个锁保护的。
当类的不变性条件涉及多个状态变量时,在不变性条件的每个变量都必须由同一个锁来保护。
当执行时间较长的计算或者可能无法快速完成的操作时(网络IO),一定不要持有锁。
本文是《Java 并发编程实战》的读书笔记。