进程与线程
Process(进程)
(2) Thread
Ways to create a thread: Subclass Thread
交错和竞争
Interleaving and Race Condition交错和竞争
时间分片是由OS自动调度的
Shared Memory among Threads(内存共享模式)
(3) Race Condition(竞争条件)
A和B同时读取余额,计算出独立的最终余额,然后快速回滚新的余额,而不考虑另一个存款。
一些事件的交织可能是好的,在某种意义上,它们与单一的、非并发的过程将产生一致,但是其他交织产生错误的答案-违反后条件不变的。
Message Passing Example
消息传递机制也无法解决竞争条件问题 仍然存在消息传递时间上的交错
Thread Safety
线程之间的“竞争条件”:作用于同一个mutable数据上的多个线程, 彼此之间存在对该数据的访问竞争并导致interleaving,导致postcondition可能被违反,这是不安全的。
Strategy 1: Confinement
Avoid Global Variables 避免全局变量!!
Strategy 2: Immutability
使用不可变数据类型和不可变引用,避免 多线程之间的race condition
不可变数据通常是线 程安全的
如果ADT中使用了beneficent mutation,必须 要通过“加锁”机制来保证线程安全
Strategy 3: Using Threadsafe Data Types
在使用synchronizedMap(hashMap)之后,不要再把参数hashMap共 享给其他线程,不要保留别名,一定要彻底销毁
即使在线程安全的集合类上,使用iterator也 是不安全的
除非使用lock机制
Strategy 4: Locks and Synchronization
程序员来负责多线程之间对mutable数据的共享操作,通过“同步” 策略,避免多线程同时访问数
使用锁机制,获得对数据的独家mutation权,其他线程被阻塞,不得访问
Synchronized Blocks and Methods
注意:要互斥,必须使用同一个lock进行 保护
对synchronized的方法,多个线程执 行它时不允许interleave,也就是说“按原子的串行方式执行”
同步机制给性能带 来极大影响
除非必要,否则不要用。Java中很多mutable 的类型都不是threadsafe就是这个原因
尽可能减 小lock的范围
Synchronized不是灵丹妙药,你的程序需要严格遵守设计原则,先尝 试其他办法,实在做不到再考虑lock。
Liveness: deadlock, starvation and livelock(死锁活锁)
死锁:多个线程竞争lock,相互等待对方释放lock
Starvation
因为其他线程lock时间太长,一个线程长时间无法获取其所需的资源 访问权(lock),导致无法往下进行。
Livelock