auto commit

This commit is contained in:
CyC2018 2019-11-30 23:03:31 +08:00
parent 8c40997b01
commit 0d350f1fb6
2 changed files with 168 additions and 156 deletions

View File

@ -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]);
}
}
```
# 进程通信
进程同步与进程通信很容易混淆它们的区别在于

View File

@ -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]);
}
}
```
# 进程通信
进程同步与进程通信很容易混淆它们的区别在于