软件构造学习笔记第七章
软件构造学习笔记第七章
并发
进程和线程:
进程独享资源:进程之间不共享内存;只能通过消息传递来进行协作
线程:
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
解除当前对象阻塞的所有进程