信号量
一个信号量是一个包含两部分内容的数据结构:
(a) 一个整数计数器, COUNT
(b) 一个记录阻塞进程ID的队列, Q
信号量有两个原子操作:
UP(V操作) 和 DOWN (P操作)
DOWN(S):
if (S.count > 0)
S.count = S.count - 1;
else
block(P);
即,
(a) 将 P进程的pid 插入 S.Q
(b) 阻塞进程 P
(c) 将控制权交给调度进程
UP(S):
if (S.Q is nonempty)
wakeup(P) 唤醒 S.Q中的某个P; 即:
(a) 将进程P的pid从队列S.Q中移除
(b) 将进程P的pid插入就绪队列
(c) 将控制权交给调度进程
else
S.count = S.count + 1;
利用信号量实现互斥
semaphore mutex = 1;
// set mutex.count = 1
DOWN(mutex);
- critical section -
UP(mutex);
信号量通过引入阻塞避免了忙等待。
习题:
设两个进程共用一个临界资源的互斥信号量mutex,当mutex=1时表示()
A 一个进程进入了临界区,另一个进程在等待;
B没有一个进程进入临界区;
C 两个进程都进入临界区;
D 两个进程都在等待;
经典的IPC问题
- 读者写者问题
- 哲学家就餐问题
- 睡眠理发师问题
1. 读者写者问题
Reader:
Down(mutex)
Read data
Up(mutex)
Writer:
Down(mutex)
Write data
Up(mutex)
问题:每次只允许一个读者读数据。
Initial: reader = 0; wmutex = 1;
Reader:
reader ++;
If(reader == 1)
Down(wmutex);
Read data
reader--;
If(reader == 0)
Up(wmutex);
Writer :
Down(wmutex)
Write data
Up(wmutex)
问题: 导致竞争条件。
方案1
Reader:
Down(mutex);
reader ++;
If(reader == 1)
Down(wmutex);
Up(mutex);
Read data
Down(mutex);
reader--;
If(reader == 0)
Up(wmutex);
Up(mutex);
Writer:
Down(wmutex)
Write data
Up(wmutex)
2. 哲学家就餐问题
五个哲学家坐在餐桌边,每两位哲学家之间有一个叉子。每个哲学家需要拿到两把叉子才能吃到面条。哲学家吃一会儿面就放下叉子思考人生,思考一会又打算吃点面条,如此循环。如何确保所有哲学家都能高效地吃面条和思考人生?
方案1
过程take-fork 将等待直到获得相应的叉子。
问题:如果五个哲学家同时感到饿了,他们将同时拿起他们左边的叉子,这将导致大家都在等待右边的叉子,谁都吃不了面条。
方案2
问题: 如果一个哲学家正在吃面条,而他旁边的哲学家请求使用叉子,那么所有其他的哲学家都必须等待直到这个请求满足。
方案3
Void philosopher(int i) {
While (True) do {
Thinking;
take_forks(i);
Eating;
put_forks(i);
}
}
目的: 用于检查是否 (i) 可以开始吃了. 如果 (i) 可以开始吃,那么更新 (i)的状态并允许 (i) 开始吃面条。否则,当执行下一个 down 操作时(i) 将被阻塞。
3. 睡眠理发师问题
有一个理发师,一张理发的椅子和n张顾客等待时坐的椅子。如果没有顾客,则理发师将睡觉;若第一个顾客进来了,他将叫醒理发师给自己理发;若顾客进来发现没有空的椅子,他将离开理发店。
解决方案
利用信号量实现同步/异步
同步与互斥的关系
- 同步:多个相互合作的进程,在一些关键节点上可能需要互相等待或互相交换信息,这种相互制约关系称为同步。
- 互斥:当一个进程进入临界区使用临界资源时,另一个进程必须等待;当占用临界资源的进程退出临界区后,另一进程才允许访问此临界资源,进程之间的这种相互制约关系称为互斥。
- 关系:互斥是同步的一种特殊情况。
习题:
这节跟上一个笔记的内容联系较大,可以移步上一个笔记看看哦