软件构造学习笔记第七章

软件构造学习笔记第七章

并发
软件构造学习笔记第七章
进程和线程:
软件构造学习笔记第七章
进程独享资源:进程之间不共享内存;只能通过消息传递来进行协作
软件构造学习笔记第七章

线程:

软件构造学习笔记第七章

Able结尾的是接口, or结尾的是类
软件构造学习笔记第七章

Race condition的例子:
软件构造学习笔记第七章

线程的中断由自己决定
Interrupted:检查是否中断,并且复位中断标识符
isInterrupted:检查是否中断
线程中断
软件构造学习笔记第七章

只有在睡眠的时候收到中断信号,才会中断线程(可以通过异常来展示)
其他时候收到中断信号,仅仅是中断标识符被改变成1.

软件构造学习笔记第七章

Join()的使用,

软件构造学习笔记第七章
线程安全的四种策略
Confinement : 限制数据共享
将可变数据限制在某个线程内部,避免竞争 不允许任何线程读写该数据

Immutability 使用不可变数据类型和不可变引用

不可变是对于用户,可能内部使用beneficent mutation。所以通常是安全的

不可变数据类型一般都是thread safe的

将集合类变为immutable类型的就能变成线程安全的:Synchronized

如果必须使用mutable类型的数据类型共享数据 java提供了decorator模式

即使是线程安全的collection类,仍能产生竞争:在操作之间可能产生竞争
例子:
软件构造学习笔记第七章

线程安全
软件构造学习笔记第七章
Locks and synchronized机制
程序员自己负责多线程之间对于 mutable数据的共享通过同步策略 避免多个线程同时访问数据

Monitor 设计模式;:把所有的方法锁住(但是效率很低)
软件构造学习笔记第七章
下图和上图意义一样
软件构造学习笔记第七章
类的构造函数是不需要锁的

另一种方法:用细粒度的锁 (多个不同的锁)
除非必要,不要使用锁
加锁不一定要对整个方法,需要仔细思考,对哪些语句加锁。

锁的要求

Happen-before即从内存中查看数据是否被修改,如果被修改就不进行操作,反之进行操作。但是也不是一定成功的。第二个图是反例

Gap buffer
gapStart ; 空白开始的位置
gapStart:空白的长度

对Static的方法加锁,相当于对类加锁,十分消耗时间。
对谁操作就把谁当锁:example(下图的就是static方法,不能直接对他加锁,要在类里面加锁,而且时堆buf修改,所以加把它当锁)

Deadlock :(例如线程A和B都需要锁1,2。但是A占有1而B占有2,都执行不下去了,一直在等对方释放锁。类似于第二图)

解决死锁(下面两个方法会消耗大量时间)
1)对锁进行排序

2)用一个粗粒度的锁代替

Wait()

Obj.notify
解除当前对象阻塞的等待
Notifyall
解除当前对象阻塞的所有进程