计算机操作系统——复习第四章进程同步与死锁,各经典同步问题中需要满足什么同步条件,死锁处理方法有哪些?某寺庙,有小和尚、老和尚若干。庙内有一水缸,由小和尚提水入缸,供老和尚饮用。水缸可容纳30桶水,

  • 一.各经典同步问题中需要满足什么同步条件?

1. 互斥:某些临界资源(如公共变量或文件)同时只能被一个进程访问,则需要采用互斥机制来避免两个或多个进程同时访问该资源。可通过信号量、互斥锁等方法实现。
2. 同步:进程之间具有所谓的“直接制约关系”,即一个进程在完成某项操作前,必须等待另一个进程执行相应的操作后才能开始自己的下一步操作,这时候需要使用同步对象进行同步。
3. 死锁避免:如果每个进程都获得了一个资源并且希望获得另一个进程拥有的资源,则可能出现死锁情况。所以需要规定顺序分配资源。
4. 进展:当所有请求进程中至少有一个可以运行时,不能进一步延迟该请求的满足,避免饥饿现象的发生。

  • 二.死锁处理方法有哪些?

1. 预防死锁:采用预防死锁的措施,尽量避免系统运行陷入死锁状态。例如,破坏进程请求资源的必要条件之一:消除互斥、占有且等待、不可剥夺、环路等条件中的任意一个。
2. 避免死锁:在运行时动态地检测系统状态,确保不会出现死锁状态。使用避免死锁算法进行检查,如银行家算法、安全顺序算法等。
3. 检测死锁:当避免死锁不可行时,可以通过定期检测系统状态来发现是否存在死锁,并采取相应的措施解除死锁。
4. 解除死锁:当检测到系统处于死锁状态时,需要采取恰当的措施对死锁进行解除。常用的方法包括终止某些进程、抢占资源、撤销进程申请的部分或全部资源,可以结合操作系统提供的算法对资源进行选择释放等。

  • 三.应用银行家算法检测系统安全状态(P145页 题4-5 第3题)。

(1)利用银行家算法T0时刻的资源分配进行分析,可得此时刻的安全性分析情况如下表所示

Work

Need

Allocation

Work+Allocation

Finish

A

B

C

A

B

C

A

B

C

A

B

C

P1

3

3

2

1

2

2

2

0

0

5

3

2

True

P3

5

3

2

0

1

1

2

1

1

7

4

3

True

P4

7

4

3

4

3

1

0

0

2

7

4

5

True

P2

7

4

5

6

0

0

3

0

2

10

4

7

True

P0

10

4

7

7

4

3

0

1

0

10

5

7

True

可知,在T0时刻存在着一个安全序列{P1,P3,P4,P2,P0},故系统是安全的。

(2)由于P1请求资源Request(1,0,2),系统按照银行家算法进行检查:

Request(1,0,2)<=Need(1,2,2)

Request(1,0,2)<=Available(3,3,2)

于是系统试探分配,修改相应的向量,形成的资源变化清况如下表所示

Max

Allocation

Need

Available

A

B

C

A

B

C

A

B

C

A

B

C

P0

7

5

3

0

1

0

7

4

3

2

3

0

P1

3

2

2

3

0

2

0

2

0

P2

9

0

2

3

0

2

6

0

0

P3

2

2

2

2

1

1

0

1

1

P4

4

3

3

0

0

2

4

3

1

再利用安全性算法检查此时系统是否安全,如下表所示

Work

Need

Allocation

Work+Allocation

Finish

A

B

C

A

B

C

A

B

C

A

B

C

P1

2

3

0

0

2

0

3

0

2

5

3

2

True

P3

5

3

2

0

1

1

2

1

1

7

4

3

True

P4

7

4

3

4

3

1

0

0

2

7

4

5

True

P0

7

4

5

7

4

3

0

1

0

7

5

5

True

P2

7

5

5

6

0

0

3

0

2

10

5

7

True

由于安全性算法检查可知,可以找到一个安全序列{P1,P3,P4,P0,P2}。因此,系统是安全的,可以立即把P1所申请的资源分配给它。

(3)由于P4发出资源请求 Request(3,3,0),系统按照银行家算法进行检查:

Request(3,3,0)<=Need(4,3,1)

Request(3,3,0)>Available(2,3,0),所以让P4等待。

(4)由于P0发出资源请求Request(0,2,0),系统按照银行家算法进行检查:

Request(0,2,0)

Request(0,2,0)<=Available(2,3,0)

于是系统试探分配,修改相应的向量,形成的资源变化清况如下表所示

Allocation

Need

Available

A

B

C

A

B

C

A

B

C

P0

0

3

0

7

2

3

2

1

0

P1

3

0

2

0

2

0

P2

3

0

2

6

0

0

P3

2

1

1

0

1

1

P4

0

0

2

4

3

1

对其进行安全性检查,可用资源Available(2,1,0)已不能满足任何进程的需要,故系统进入不安全状态,此时系统不分配资源。

  • 四.完成以下各题伪代码。

  1. 某寺庙,有小和尚、老和尚若干。庙内有一水缸,由小和尚提水入缸,供老和尚饮用。水缸可容纳30桶水,每次入水、取水仅为1桶,不可同时进行。水取自同一井中,水井径窄,每次只能容纳一个水桶取水。设水桶个数为5个,试用信号量和P、V操作的伪代码给出老和尚和小和尚的活动。
semaphore empty= 30; //表示缸中目前还能装多少桶水,初始时能装30桶水
semaphore full=0; //表示缸中有多少桶水,初始时缸中没有水
semaphore buckets =5; //表示有多少只空桶可用,初始时有5只桶可用
semaphore mutex_well=1; //用于实现对井的互斥操作
semaphore mutex bigjar =1; //用于实现对缸的互斥操作
young_monk(){
while(1){
P(empty);
P(buckets);
go to the well;P(mutex_well);get water;
V(mutex_well);go to the temple;P(mutex _bigjar);}
pure the water into the big jar; }
V(mutex_bigjar);
V(buckets);
V(fu11);

old_monk(){
while(){
P(ful1);
P(buckets);
P(mutex_bigjar);
get water;
V(mutex_bigjar);
drink wateri
V(buckets);
V(empty);

}
}
  1. 一座小桥(最多只能承重两个人)横跨南北两岸,任意时刻同一方向只允许一人过桥,南侧桥段和北侧桥段较窄只能通过一人,桥中央一处宽敞,允许两个人通过或歇息。试用信号量和P、V操作写出南、北两岸过桥的同步算法。

分析题意可知,小桥可能有3种状态:桥上可能没有人,也可能有一人,也可能有两人。
当相向两人过桥时也可能有3种状态:
(a)两人同时上桥;(b)两人都到中间;(c)南(北)来者到北(南)段。
共需要3个信号量,load用来控制桥上人数,初值为2,表示桥上最多有两人;north用来控制北段桥的使用,初值为1,用于对北段桥互斥;south用来控制南段桥的使用,初值为1,用于对南段桥互斥。

算法如下:

semaphore load =2;

semaphore north=1;

semaphore south=1;
tosouth(){ tonorth(){
P(load);   P(load);

P(south); P(north);

过北段桥; 过南段桥;

到桥中间;  到桥中间

V(north); V(south);

P(south); P(north);

过南段桥 过北段桥;

到达南岸 到达北岸

V(south); V(north);

V(load); V(load);
  1. 假设图书馆阅览室共有100个座位。读者进入时必须先在登记表上登记,该表为每一座位登记一个记录,包括座号和读者姓名。读者离开时要注销掉登记内容。请用信号量及操作的伪代码实现读者进入阅览室的同步过程

可以使用两个信号量来实现这个同步过程,分别是“空闲座位”和“登记表”,初始值分别为100和1。
semaphore emptySeat = 100; // 空闲座位数量
semaphore registry = 1;    // 登记表可用

void reader_enter(string name, int seat) {
    wait(emptySeat); // 等待空闲座位
    wait(registry);  // 获取登记表

    // 在登记表上登记
    registerSeat(name, seat);

    signal(registry);   // 释放登记表
}

void reader_leave(int seat) {
    wait(registry);     // 获取登记表

    // 在登记表上注销
    unregisterSeat(seat);

    signal(registry);   // 释放登记表
    signal(emptySeat);  // 空闲座位数量加一
}

这里用了`wait`和`signal`两个信号量操作。当读者进入阅览室时,首先会等待`emptySeat`信号量,表示等待有空闲座位。一旦获取到了空闲座位,就会等待`registry`信号量,表示获取了登记表。在获取到登记表后,会在登记表上登记该读者的信息,并在此后释放`registry`信号量。读者离开阅览室时,则需要重新获取`registry`信号量,并在登记表上注销该座位的记录。注销后,先释放`registry`信号量,再通过`signal`操作将空闲座位数量加一。

  1. 在公共汽车上,司机和售票员各行其职,司机负责开车和到站停车;售票员负责售票和开、关车门司机停车后售票员才能开门;当售票员关好车门后司机才能开车行驶。请用信号量及操作的伪代码实现司机和售票员的同步过程

可以使用两个信号量来实现这个同步过程,分别是“售票员”和“司机”,初始值都为0。

semaphore driver = 0;    // 初始值为0
semaphore conductor = 0; // 初始值为0

// 司机的行为
void driver_behavior() {
    while (true) {
        // 开车行驶
        drive();

        // 等待售票员关好车门
        wait(conductor);
    }
}

// 售票员的行为
void conductor_behavior() {
    while (true) {
        // 售票
        sellTicket();

        // 关闭车门
        closeDoor();

        signal(driver);     // 唤醒司机开车
        wait(conductor);    // 等待司机停车
        openDoor();         // 开门放客
    }
}

// 司机停车的操作
void driver_stop() {
    stop();
    signal(conductor);  // 唤醒售票员开门
    wait(driver);      // 等待售票员关门
}

这里用了`wait`和`signal`两个信号量操作。当售票员完成了售票和关门操作后,会通过`signal`操作唤醒等待在`driver`信号量上的司机,表示已经准备好让车行驶了。同时,售票员也会在`conductor`信号量上等待司机完成了停车操作后再开门。

当司机完成了停车操作后,会通过`signal`操作唤醒等待在`conductor`信号量上的售票员开门。而售票员也会在完成了开门操作后再次等待司机关门完成。

  1. 在4×100米接力赛中,4个运动员之间存在如下关系,运动员1跑到终点把接力棒交给运动员2;运动员2一开始处于等待状态,在接到运动员1传来的接力棒后才能往前跑,他跑完100米后交给运动员3,运动员3也只有在接到运动员2传来的棒后才能跑,他跑完100米后交给运动员4,运动员4接到棒后跑完全程。请用信号量及操作的伪代码实现运动员接力的同步过程

可以使用三个信号量来实现这个同步过程,分别是“棒1”,“棒2”和“棒3”,初始值都为0。
semaphore baton1 = 0;   // 初始值为0 
semaphore baton2 = 0;   // 初始值为0 
semaphore baton3 = 0;   // 初始值为0 

void runner1_behavior() {
    // 跑到终点把接力棒交给运动员2
    run();
    signal(baton1);     // 传递接力棒,唤醒运动员2
}

void runner2_behavior() {
    wait(baton1);            // 等待接力棒,运动员1传来棒后才能开始跑
    // 跑完100米后交给运动员3
    run();
    signal(baton2);           // 传递接力棒,唤醒运动员3
}

void runner3_behavior() {
    wait(baton2);            // 等待接力棒,运动员2传来棒后才能开始跑
    // 跑完100米后交给运动员4
    run();
    signal(baton3);           // 传递接力棒,唤醒运动员4
}

void runner4_behavior() {
    wait(baton3);            // 等待接力棒,运动员3传来棒后才能开始跑
    // 跑完100米,比赛结束
    run();
}
  1. 了`wait`和`signal`两个信号量操作。初始状态下,所有的运动员都在等待状态,只有当前一个运动员传递了接力棒后,才会唤醒下一个运动员开始跑。
  2. 当运动员1完成自己的100米后,经过`signal(baton1)`操作,使得等待在`baton1`上的运动员2被唤醒,开始跑步。随着运动员2经过100米交接给运动员3,使用`signal(baton2)`操作让等待在`baton2`上的运动员3被唤醒继续跑步。同理,当运动员3完成自己的100米之后,使用`signal(baton3)`操作让等待在`baton3`上的运动员4被唤醒,完成比赛。

你可能感兴趣的:(操作系统,java,开发语言,算法,数学建模)