笔记而已
do {
entry section;
critical section;
exit section;
remainder section;
} while(true)
- 同步
- 空闲让进
- 忙则等待
- 有限等待
- 让权等待
软件实现方法
单标志法
P0:
while(turn != 0);
critical section;
turn = 1;
remainder section;
P1:
while(turn != 1);
critical section;
turn = 0;
remainder section;
必须交替进入,违反空闲让进
双标志法先检查
Pi:
while(flag[j]); 1
flag[i] = true; 3
critical section;
flag[i] = false;
remainder section;
Pj:
while(flag[i]); 2
flag[j] = true; 4
critical section;
flag[j] = false;
remainder section;
可不用交替进入
但是1234可能同时进入,违反忙则等待
双标志法后检查
Pi:
flag[i] = true;
while(flag[j]);
critical section;
flag[i] = false;
remainder section;
Pj:
flag[j] = true;
while(flag[i]);
critical section;
flag[j] = false;
remainder section;
都进不去,卡在while,饥饿
Peterson’s Algorithm
Pi:
flag[i] = true; turn = j;
while(flag[j] && turn == j);
critical section;
flag[i] = false;
remainder section;
Pj:
flag[j] = true; turn = i;
while(flag[i] && turn == i);
critical section;
flag[j] = false;
remainder section;
硬件实现方法
中断屏蔽方法
……
关中断;
临界区;
开中断;
……
方便,效率低,不适合多处理机、用户进程
硬件指令方法
TestAndSet指令:原子操作
boolean TestAndSet(boolean *lock) {
boolean old;
old = *lock;
*lock = true;
return old;
}
while TestAndSet(&lock);
critical section;
lock = false;
reaminder section;
Swap指令
Swap(boolean *a, boolean *b) {
boolean temp;
temp = *a;
*a = *b;
*b = temp;
}
key = true;
while(key != false)
Swap(&lock, &key);
critical section;
lock = false;
remainder section;
没啥区别,简单
适合多处理机
不满足让权等待,暂时进不去的会循环TSL,忙等
信号量
- wait(S) P-
- signal(S) V+
整型信号量
wait(S) {
while(S <= 0); // busy waiting
S = S - 1;
}
signal(S) {
S = S + 1;
}
忙等,不满足让权等待
记录型信号量
typedef struct {
int value;
struct process *L; // waiting queue
} semaphore;
void wait (semaphore S) { // 申请资源
S.value--;
if (S.value < 0) {
add this process to S.L;
block(S.L);
}
}
void signal (semaphore S) { // 释放资源
S.value++;
if (S.value <= 0) {
remove a process P from S.L;
wakeup(P);
}
}
同步
x -> y
semaphore S = 0;
P1() {
...
x;
V(S);
...
}
P2() {
...
P(S);
y;
...
}
互斥
semaphore mutex = 1;
P1() {
...
P(mutex);
critical section;
V(mutex);
...
}
P2() {
...
P(mutex);
critical section;
V(mutex);
...
}
前驱
同步的加强多重版
- 方法
- 关系分析:同步、互斥、前驱
- 整理思路:PV大致顺序
- 设置信号量及初值
管程monitor
def
monitor Demo { // 1. 管程的名称
// 2. 定义共享数据结构,对应系统中的某种共享资源
共享数据结构S;
// 4. init shared DS
init_code() {
S = 5;
}
// 3. process1: apply for a res
take_away() {
... to SDS x;
S--;
...
}
// 3. process2: return a res
give_back() {
... to SDS x;
S++;
...
}
}
- 像class
- 封装对sds的操作
- 每次仅允许一个进去,所以互斥
条件变量condition
monitor Demo {
SDS S;
condition x;
init_code() {...};
take_away() {
if (S <= 0) x.wait();
allocate res;
}
give_back() {
return res;
if (S <= 0) x.signal(); // awaken
}
}
- cmp - Semaphore
- x的wait/signal类似P/V
- no value, sds记录res
经典同步问题
producer-consumer
- 关系分析
- 生产者/消费者 —— buf:互斥
- 生产者 —— 消费者:同步
- 生产者生产了以后,消费者才可以消费
- 整理思路
- 信号量
- mutex = 1,buf
- full = 0
- empty = n
semaphore mutex = 1;
semaphore empty = n;
semaphore full = 0;
producer() {
while(1) {
produce;
P(empty);
P(mutex);
add item to buffer;
V(mutex);
V(full);
}
}
consumer() {
while(1) {
P(full);
P(mutex);
remove an item from buffer;
V(mutex);
V(empty);
consume;
}
}
进阶:母子橘,父女苹果
- 关系分析
- 父母互斥
- 父女、母子——同步
- 整理思路
- 2个生产者,2个消费者,buf大小为1
- 信号量
- plate = 1, mutex
- apple = 0, orange = 0
semaphore plate = 1, apple = 0, orange = 0;
dad() {
while(1) {
prepare an apple;
P(plate);
put the apple on the plate;
V(apple);
}
}
mom() {
while(1) {
prepare an orange;
P(plate);
put the orange on the plate;
V(apple);
}
}
son() {
while(1) {
P(orange);
take an orange from the plate;
V(plate);
eat the orange;
}
}
daughter() {
while(1) {
P(apple);
take an apple from the plate;
V(plate);
eat the apple;
}
}
reader-writer
- 关系分析
- 读写互斥
- 写写互斥
- 读读没有关系
- 整理思路
- 写:PV互斥
- 读:计数器
- 读、计数器——互斥
- 信号量
- count = 0
- mutex = 1
- rw = 1 (读写互斥)
- count = 0
int count = 0;
semaphore mutex = 1;
semaphore rw = 1;
writer() {
while(1) {
P(rw);
write;
V(rw);
}
}
reader() {
while(1) {
P(mutex);
if (count == 0) // 第一个读的记得阻止写,之后就没事儿了
P(rw);
count++;
V(mutex);
read;
P(mutex);
count--;
if (count == 0) // 最后一个读的通知写OK了
V(rw);
V(mutex);
}
}
- 写优先:WD的会堵塞
哲学家吃饭
-
关系分析
- 互斥:五个哲学家与左右邻居——中间的筷子
-
整理思路
-
一个哲学家拿到左右两根筷子且不死锁、饥饿
-
方法一:同时拿两根
- 先拿左后拿右——如果大家都拿起了左边的,GG
-
方法二:限制动作
- 左右都能用时,才拿筷子吃饭
- !拿筷子这件事设置信号量
-
-
信号量
- 互斥 chopstick[5] = {1}
- 哲学家i:0~4
- i左边的筷子:i
- i右边的筷子:(i + 1) % 5
- 拿筷子 mutex = 1
semaphore chopstick[5] = {1};
semaphore mutex = 1;
Pi() {
while(1) {
P(mutex);
P(chopstick[i]);
P(chopstick[(i + 1) % 5]);
V(mutex);
eat;
V(chopstick[i]);
V(chopstick[(i + 1) % 5]);
think;
}
}
吸烟者问题
3 smoker,1 provider
smo卷烟、抽,材料:烟草、paper、glue,各有一个,pro无限提供
pro每次放两个材料,正好ok的人卷烟,抽完了告诉prov,prov持续重复让三个smo轮流抽
- 关系分析
- pro & 3smo :同步
- 3smo:互斥
- 整理思路
- 4个process
- 信号量
- offer1, offer2, offer3 —— res
- finish —— 抽完了
int num = 0;
semaphore offer1 = 0;
semaphore offer2 = 0;
semaphore offer3 = 0;
semaphore finish = 0;
process P1() { // pro
while(1) {
num = (num + 1) % 3;
if (num == 0)
V(offer1);
else if (num == 1)
V(offer2);
else
V(offer3);
put materials on the table;
P(finish);
}
}
// 3smo
process P1() { // pro
while(1) {
P(offer1);
smoke;
V(finish);
}
}
process P2() { // pro
while(1) {
P(offer2);
smoke;
V(finish);
}
}
process P3() { // pro
while(1) {
P(offer3);
smoke;
V(finish);
}
}