auto commit
This commit is contained in:
parent
8c40997b01
commit
0d350f1fb6
@ -14,8 +14,8 @@
|
||||
* [3. 信号量](#3-信号量)
|
||||
* [4. 管程](#4-管程)
|
||||
* [经典同步问题](#经典同步问题)
|
||||
* [1. 读者-写者问题](#1-读者-写者问题)
|
||||
* [2. 哲学家进餐问题](#2-哲学家进餐问题)
|
||||
* [1. 哲学家进餐问题](#1-哲学家进餐问题)
|
||||
* [2. 读者-写者问题](#2-读者-写者问题)
|
||||
* [进程通信](#进程通信)
|
||||
* [1. 管道](#1-管道)
|
||||
* [2. FIFO](#2-fifo)
|
||||
@ -306,7 +306,87 @@ end;
|
||||
|
||||
生产者和消费者问题前面已经讨论过了。
|
||||
|
||||
## 1. 读者-写者问题
|
||||
## 1. 哲学家进餐问题
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
|
||||
|
||||
五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。
|
||||
|
||||
下面是一种错误的解法,如果所有哲学家同时拿起左手边的筷子,那么所有哲学家都在等待其它哲学家吃完并释放自己手中的筷子,导致死锁。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think();
|
||||
take(i); // 拿起左边的筷子
|
||||
take((i+1)%N); // 拿起右边的筷子
|
||||
eat();
|
||||
put(i);
|
||||
put((i+1)%N);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
为了防止死锁的发生,可以设置两个条件:
|
||||
|
||||
- 必须同时拿起左右两根筷子;
|
||||
- 只有在两个邻居都没有进餐的情况下才允许进餐。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
#define LEFT (i + N - 1) % N // 左邻居
|
||||
#define RIGHT (i + 1) % N // 右邻居
|
||||
#define THINKING 0
|
||||
#define HUNGRY 1
|
||||
#define EATING 2
|
||||
typedef int semaphore;
|
||||
int state[N]; // 跟踪每个哲学家的状态
|
||||
semaphore mutex = 1; // 临界区的互斥,临界区是 state 数组,对其修改需要互斥
|
||||
semaphore s[N]; // 每个哲学家一个信号量
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think(i);
|
||||
take_two(i);
|
||||
eat(i);
|
||||
put_two(i);
|
||||
}
|
||||
}
|
||||
|
||||
void take_two(int i) {
|
||||
down(&mutex);
|
||||
state[i] = HUNGRY;
|
||||
check(i);
|
||||
up(&mutex);
|
||||
down(&s[i]); // 只有收到通知之后才可以开始吃,否则会一直等下去
|
||||
}
|
||||
|
||||
void put_two(i) {
|
||||
down(&mutex);
|
||||
state[i] = THINKING;
|
||||
check(LEFT); // 尝试通知左右邻居,自己吃完了,你们可以开始吃了
|
||||
check(RIGHT);
|
||||
up(&mutex);
|
||||
}
|
||||
|
||||
void eat(int i) {
|
||||
down(&mutex);
|
||||
state[i] = EATING;
|
||||
up(&mutex);
|
||||
}
|
||||
|
||||
// 检查两个邻居是否都没有用餐,如果是的话,就 up(&s[i]),使得 down(&s[i]) 能够得到通知并继续执行
|
||||
void check(i) {
|
||||
if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] !=EATING) {
|
||||
state[i] = EATING;
|
||||
up(&s[i]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 读者-写者问题
|
||||
|
||||
允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
|
||||
|
||||
@ -345,7 +425,7 @@ void writer() {
|
||||
|
||||
The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer).
|
||||
|
||||
```source-c
|
||||
```c
|
||||
int readcount, writecount; //(initial value = 0)
|
||||
semaphore rmutex, wmutex, readLock, resource; //(initial value = 1)
|
||||
|
||||
@ -450,80 +530,6 @@ void reader()
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 2. 哲学家进餐问题
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
|
||||
|
||||
五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。
|
||||
|
||||
下面是一种错误的解法,考虑到如果所有哲学家同时拿起左手边的筷子,那么就无法拿起右手边的筷子,造成死锁。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think();
|
||||
take(i); // 拿起左边的筷子
|
||||
take((i+1)%N); // 拿起右边的筷子
|
||||
eat();
|
||||
put(i);
|
||||
put((i+1)%N);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
为了防止死锁的发生,可以设置两个条件:
|
||||
|
||||
- 必须同时拿起左右两根筷子;
|
||||
- 只有在两个邻居都没有进餐的情况下才允许进餐。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
#define LEFT (i + N - 1) % N // 左邻居
|
||||
#define RIGHT (i + 1) % N // 右邻居
|
||||
#define THINKING 0
|
||||
#define HUNGRY 1
|
||||
#define EATING 2
|
||||
typedef int semaphore;
|
||||
int state[N]; // 跟踪每个哲学家的状态
|
||||
semaphore mutex = 1; // 临界区的互斥
|
||||
semaphore s[N]; // 每个哲学家一个信号量
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think();
|
||||
take_two(i);
|
||||
eat();
|
||||
put_two(i);
|
||||
}
|
||||
}
|
||||
|
||||
void take_two(int i) {
|
||||
down(&mutex);
|
||||
state[i] = HUNGRY;
|
||||
test(i);
|
||||
up(&mutex);
|
||||
down(&s[i]);
|
||||
}
|
||||
|
||||
void put_two(i) {
|
||||
down(&mutex);
|
||||
state[i] = THINKING;
|
||||
test(LEFT);
|
||||
test(RIGHT);
|
||||
up(&mutex);
|
||||
}
|
||||
|
||||
void test(i) { // 尝试拿起两把筷子
|
||||
if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] !=EATING) {
|
||||
state[i] = EATING;
|
||||
up(&s[i]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# 进程通信
|
||||
|
||||
进程同步与进程通信很容易混淆,它们的区别在于:
|
||||
|
@ -14,8 +14,8 @@
|
||||
* [3. 信号量](#3-信号量)
|
||||
* [4. 管程](#4-管程)
|
||||
* [经典同步问题](#经典同步问题)
|
||||
* [1. 读者-写者问题](#1-读者-写者问题)
|
||||
* [2. 哲学家进餐问题](#2-哲学家进餐问题)
|
||||
* [1. 哲学家进餐问题](#1-哲学家进餐问题)
|
||||
* [2. 读者-写者问题](#2-读者-写者问题)
|
||||
* [进程通信](#进程通信)
|
||||
* [1. 管道](#1-管道)
|
||||
* [2. FIFO](#2-fifo)
|
||||
@ -306,7 +306,87 @@ end;
|
||||
|
||||
生产者和消费者问题前面已经讨论过了。
|
||||
|
||||
## 1. 读者-写者问题
|
||||
## 1. 哲学家进餐问题
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
|
||||
|
||||
五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。
|
||||
|
||||
下面是一种错误的解法,如果所有哲学家同时拿起左手边的筷子,那么所有哲学家都在等待其它哲学家吃完并释放自己手中的筷子,导致死锁。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think();
|
||||
take(i); // 拿起左边的筷子
|
||||
take((i+1)%N); // 拿起右边的筷子
|
||||
eat();
|
||||
put(i);
|
||||
put((i+1)%N);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
为了防止死锁的发生,可以设置两个条件:
|
||||
|
||||
- 必须同时拿起左右两根筷子;
|
||||
- 只有在两个邻居都没有进餐的情况下才允许进餐。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
#define LEFT (i + N - 1) % N // 左邻居
|
||||
#define RIGHT (i + 1) % N // 右邻居
|
||||
#define THINKING 0
|
||||
#define HUNGRY 1
|
||||
#define EATING 2
|
||||
typedef int semaphore;
|
||||
int state[N]; // 跟踪每个哲学家的状态
|
||||
semaphore mutex = 1; // 临界区的互斥,临界区是 state 数组,对其修改需要互斥
|
||||
semaphore s[N]; // 每个哲学家一个信号量
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think(i);
|
||||
take_two(i);
|
||||
eat(i);
|
||||
put_two(i);
|
||||
}
|
||||
}
|
||||
|
||||
void take_two(int i) {
|
||||
down(&mutex);
|
||||
state[i] = HUNGRY;
|
||||
check(i);
|
||||
up(&mutex);
|
||||
down(&s[i]); // 只有收到通知之后才可以开始吃,否则会一直等下去
|
||||
}
|
||||
|
||||
void put_two(i) {
|
||||
down(&mutex);
|
||||
state[i] = THINKING;
|
||||
check(LEFT); // 尝试通知左右邻居,自己吃完了,你们可以开始吃了
|
||||
check(RIGHT);
|
||||
up(&mutex);
|
||||
}
|
||||
|
||||
void eat(int i) {
|
||||
down(&mutex);
|
||||
state[i] = EATING;
|
||||
up(&mutex);
|
||||
}
|
||||
|
||||
// 检查两个邻居是否都没有用餐,如果是的话,就 up(&s[i]),使得 down(&s[i]) 能够得到通知并继续执行
|
||||
void check(i) {
|
||||
if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] !=EATING) {
|
||||
state[i] = EATING;
|
||||
up(&s[i]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 读者-写者问题
|
||||
|
||||
允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
|
||||
|
||||
@ -345,7 +425,7 @@ void writer() {
|
||||
|
||||
The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer).
|
||||
|
||||
```source-c
|
||||
```c
|
||||
int readcount, writecount; //(initial value = 0)
|
||||
semaphore rmutex, wmutex, readLock, resource; //(initial value = 1)
|
||||
|
||||
@ -450,80 +530,6 @@ void reader()
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 2. 哲学家进餐问题
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
|
||||
|
||||
五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。
|
||||
|
||||
下面是一种错误的解法,考虑到如果所有哲学家同时拿起左手边的筷子,那么就无法拿起右手边的筷子,造成死锁。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think();
|
||||
take(i); // 拿起左边的筷子
|
||||
take((i+1)%N); // 拿起右边的筷子
|
||||
eat();
|
||||
put(i);
|
||||
put((i+1)%N);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
为了防止死锁的发生,可以设置两个条件:
|
||||
|
||||
- 必须同时拿起左右两根筷子;
|
||||
- 只有在两个邻居都没有进餐的情况下才允许进餐。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
#define LEFT (i + N - 1) % N // 左邻居
|
||||
#define RIGHT (i + 1) % N // 右邻居
|
||||
#define THINKING 0
|
||||
#define HUNGRY 1
|
||||
#define EATING 2
|
||||
typedef int semaphore;
|
||||
int state[N]; // 跟踪每个哲学家的状态
|
||||
semaphore mutex = 1; // 临界区的互斥
|
||||
semaphore s[N]; // 每个哲学家一个信号量
|
||||
|
||||
void philosopher(int i) {
|
||||
while(TRUE) {
|
||||
think();
|
||||
take_two(i);
|
||||
eat();
|
||||
put_two(i);
|
||||
}
|
||||
}
|
||||
|
||||
void take_two(int i) {
|
||||
down(&mutex);
|
||||
state[i] = HUNGRY;
|
||||
test(i);
|
||||
up(&mutex);
|
||||
down(&s[i]);
|
||||
}
|
||||
|
||||
void put_two(i) {
|
||||
down(&mutex);
|
||||
state[i] = THINKING;
|
||||
test(LEFT);
|
||||
test(RIGHT);
|
||||
up(&mutex);
|
||||
}
|
||||
|
||||
void test(i) { // 尝试拿起两把筷子
|
||||
if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] !=EATING) {
|
||||
state[i] = EATING;
|
||||
up(&s[i]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# 进程通信
|
||||
|
||||
进程同步与进程通信很容易混淆,它们的区别在于:
|
||||
|
Loading…
Reference in New Issue
Block a user