# 【操作系统】经典的同步问题(生产者消费者问题, 哲学家进餐问题, 读写问题)

## 生产者-消费者问题

### 法一:记录型信号量

//生产者消费者问题
//记录型信号量
//缓冲池中有n个缓冲区, 互斥信号量mutex,
//信号量empty表示空缓冲区数量, full表示满缓冲区的数量
int in = out = 0;
item buffer[n];
semaphore mutex = 1, empty = n, full = 0;
void producer() {
do {
producer an item nextp;
wait(empty);
wait(mutex);
buffer[in] = nextp;
in = (in + 1) % n;
signal(mutex);
signal(full);
} while(true);
}
void consumer() {
do {
wait(full);
wait(mutex);
nextc = buffer[out];
out = (out + 1) % n;
signal(mutex);
signal(empty);
consumer the item in nextc;
} while(true);
}
void main() {
cobegin
producer();
consumer();
coend
}

### 法二:AND型信号量

//AND型信号量
//Swait(empty, mutex)代替wait(empty)和wait(mutex)
//Ssignal(mutex,full)代替signal(mutext)和signal(full)
//Swait(full, mutex)代替wait(full)和wait(mutex)
//Ssignal(mutex, empty)代替signal(mutex)和signal(empty)
int in = out = 0;
item buffer[n];
semaphore mutex = 1, empty = n, full = 0;
void producer() {
do {
producer an item nextp;
Swait(empty, mutex);
buffer[in] = nextp;
in = (in + 1) % n;
Ssignal(mutex, full);
} while(true);
}
void consumer() {
do {
Swait(full, mutex);
nextc = buffer[out];
out = (out + 1) % n;
Ssignal(mutex, empty);
consumer the item in nextc;
} while(true);
}
void main() {
cobegin
producer();
consumer();
coend
}

### 法三: 管程

//管程
//建立管程producerconsumer,PC
/*
put(x), 生产者利用该过程将自己生产的产品投放到缓冲池中, 并用整型变量count表示缓冲池中已有的产品数目,当
count>=N时, 表示缓冲池已满,生产者需等待.
get(x), 消费者利用该过程从缓冲池中取出一个产品, 当count<=0时, 表示缓冲池已无可用的产品, 消费者需等待
condition 为notfull和notempty
cwait(condition), 当管程被一个进程占用时, 其他进程调用该进程时阻塞, 并挂在条件condition的队列上
csignal(condition), 唤醒在cwait执行后阻塞在条件condition队列上的进程, 如果这样的进程不止一个, 则选择其中一个

*/
Monitor producerconsumer {
item buffer[N];
int in, out;
condition notfull, notempty;
int count;
public:
void put(item x) {
if (count >= N) cwait(notfull);
buffer[in] = x;
in = (in + 1) % N;
count++;
ssignal(notempty);
}
void get(item x) {
if (count <= 0) cwait(notempty);
x = buffer[out];
out = (out + 1) % N;
count--;
csignal(notfull);
}
{
in = 0;
out = 0;
count = 0;
}
}PC;

void producer() {
item x;
while (true) {
producer an item in nextp;
PC.put(x);
}
}
void consumer() {
item x;
while (true) {
PC.get(x);
consumer the item in nextc;
}
}
void main() {
cobegin
producer();
consumer();
coend
}

## 哲学家进餐问题

### 法一:记录型信号量

do {
wait(chopstick[i]);
wait(chopstick[(i + 1) % 5]);
//eat
signal(chopstick[i]);
signal(chopstick[(i + 1) % 5]);
//think
} while (true);

1.至多允许四位哲学家拿同一边的筷子, 则可让至少一位哲学家先用餐, 用餐完后释放筷子进而让其他哲学家有机会用餐.

2.五位哲学家先竞争奇数(偶数)好筷子, 在竞争偶数(奇数)号筷子, 总会有一位哲学家能进餐.

### 法二: AND型信号量

//AND型信号量
semaphore chopstick[5] = {1, 1, 1, 1, 1};
do {
//think
Swait(chopsitck[(i + 1) % 5], chopsitck[i]);
//eat
Ssignal(chopsitck[(i + 1) % 5], chopsitck[i]);
} while (true);

## 读者-写者问题

//记录型信号量
semaphore rmutext = 1, wmutext = 1;
do {
wait(rmutex);
wait(wmutex);
}
signal(rmutex);

wait(rmutex);
signal(wmutext);
}
signal(rmutex);
} while (true);
}

void Writer() {
do {
wait(wmutex);
perform write operation;
signal(wmutex);
} while (true);
}
void main() {
cobegin
Writer();
coend
}

//信号量集
int RN;
semaphore L = RN, mx = 1;
do {
Swait(L, 1, 1);
Swait(mx, 1, 0);

Ssignal(L, 1);
} while (true);
}
void Writer() {
do {
Swait(mx, 1, 1; L, RN, 0);
perform write operation;
Ssignal(mx, 1);
} while (true);
}

void main() {
cobegin
}