信号量与PV操作
解决进程同步与互斥问题的机制。
1. 信号量
一种特殊变量,表现形式是一个整数Semaphore和一个队列。
S>=0时,S表示可用资源的数量。
S<0时,已经没有可用资源,S的绝对值表示当前等待该资源的进程数。
2. P操作
S=S-1
使用资源,此时如果S<0,则挂起该进程。
3. V操作
S=S+1
释放资源,此时如果S<0,从阻塞队列里唤醒一个进程。
4. 互斥控制
互斥控制为了保护共享资源,不让多个进程同时访问该资源。
这种一次只让一个进程访问的资源称为临界资源,信号量初值设为1。
在互斥关系中,PV操作在一个进程中成对出现。
P(S) |
临界区 |
V(S) |
5. 同步控制
最简单同步形式是A在B到达L2之前不能超过L1。
设置信号量S初值为0,A到达L1后执行P操作后挂起,直到B到达L2后执行V操作将A唤醒。
在同步操作中,PV操作在两个甚至多个进程中成对出现。
进程A | 进程B |
L1 P(S) | L2 V(S) |
6. 生产者消费者问题
也称有限缓冲问题。生产者生成数据项放到缓冲区(Bound为N)中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。
要解决该问题,就必须让生产者在缓冲区满时休眠,等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。
信号量 | 初值 | 描述 |
Empty | N | 缓冲区空项数 |
Full | 0 | 缓冲区非空项数 |
Mutex | 1 | 互斥 |
生产者 | 消费者 |
P(Empty) P(Mutex) 缓冲区加数据项 V(Mutex) V(Full) | P(Full) P(Mutex) 缓冲区减数据项 V(Mutex) V(Empty) |
7. 读者作者问题
指多个进程对一个共享资源进行读写操作的问题,多个进程同时读是可以接受的,同时只能有一个进程写,写时不能读。
写者要等到没有读者的时候才能去写文件,所有读者要等待写者写完文件后才能去读文件。
信号量 | 初值 | 描述 |
ReadMutex | 1 | 读互斥 |
WriteMutex | 1 | 写互斥 |
变量 | 初值 | 描述 |
Count | 0 | 读者数 |
读者 | 写者 |
P(ReadMutex) if(Count == 0) P(WriteMutex) ++Count V(ReadMutex) 读数据 P(ReadMutex) --Count if(Count == 0) V(WriteMutex) V(ReadMutex) | P(WriteMutex) 写数据 V(WriteMutex) |
8. 理发师问题
理发店理有一位理发师、一把理发椅和N把供等候理发的顾客坐的椅子如果没有顾客,理发师便在理发椅上睡觉一个顾客到来时,它必须叫醒理发师如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,就坐下来等待,否则就离开。
信号量 | 初值 | 描述 |
Customers | 0 | 等候的顾客数 |
Barbers | 0 | 等候的理发师数,0或1 |
Mutex | 1 | Count访问互斥 |
变量 | 初值 | 描述 |
Count | 0 | 椅子上等待的顾客数,Bound为N |
理发师 | 顾客 |
P(Customers) P(Mutex) --Count V(Barbers) V(Mutex) 理发师理发 | P(Mutex) if(Count < N){ ++Count V(Mutex) V(Customers) P(Barbers) 顾客被理发 }else V(Mutex) |
9. 哲学家进餐问题
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。
哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。
参考资料: