1、信号量机制实现进程互斥
-
分析并发进程的关键活动,划定临界区(如:对临界资源打印机的访问就应放在临界区)
-
设置 互斥信号量 \color{red}互斥信号量 互斥信号量
mutex
, 初值为 1 \color{red}初值为 1 初值为1 -
在临界区之前执行
P(mutex)
-
在临界区之后执行
V(mutex)
要会自己定义记录型信号量,但如果题目中没特别说明,可以把信号量的声明简写成这种形式
semaphore mytex = 1
注意:对不同的临界资源需要设置不同的互斥信号量
P、V 操作必须成对出现 \color{red}\texttt{P、V} 操作必须成对出现 P、V操作必须成对出现
- 缺少
P(mutex)
就不能保证临界资源的互斥访问 - 缺少
V(mutex)
会导致资源用不被释放,等待进程永不被唤醒
2、用信号量机制实现进程同步
比如,P1
、P2
并发执行,由于存在异步性,因此二者交替推进的次序是不确定的。
若 P2
的 “代码 4 ” 要基于 P1
的 “代码 1 ” 和 “代码 2 ” 的运行结果才能执行,
- 那么我们就必须保证 “代码 4 ” 一定是在 “代码 2 ” 之后才会执行。
这就是进程同步问题,让本来异步并发的进程互相配合,有序推进。
用信号量实现进程同步
-
分析什么地方需要实现 “同步关系” ,即必须保证 “一前一后” 执行的两个操作(或两句代码)
-
设置 同步信号量 \color{red}同步信号量 同步信号量 S, 初始为 0 \color{red}初始为0 初始为0
-
在 “前操作” 之后 \color{red}之后 之后执行
V(S)
-
在 “后操作” 之前 \color{red}之前 之前执行
P(S)
若先执行到 V(S)
操作,则 S++
后 S=1
。
- 之后当执行到
P(S)
操作时,由于S=1
,表示有可用资源,会执行S--
,S
的值变回0
,P2
进程不会执行block
原语,而是继续往下执行代码 4 4 4。 - 说明代码 2 2 2 肯定是先于代码 4 4 4 执行的
若先执行到 P(S)
操作,由于 S=0
,S--
后 S=-1
,表示此时没有可用资源,
- 因此
P
操作中会执行block
原语,主动请求阻塞。之后当执行完代码 2 2 2,继而执行V(S)
操作,S++
,使 S变回 0 0 0,由于此时有进程在该信号量对应的阻塞队列中,因此会在V
操作中执行wakeup
原语,唤醒P2
进程。这样P2
就可以继续执行代码 4 4 4 了
可以理解为 Java
中的 LockSupport.park()
与 LockSupport.unpark(...)
LockSupport.park()
对应P(S)
LockSupport.unpark(...)
对应V(S)
3、用信号量机制实现前驱关系!!
4、整体框架
除了互斥、同步问题外,还会考察有多个资源的问题,有多少资源就把信号量初值设为多少。
- 申请资源时进行
P
操作,释放资源时进行V
操作即可