我用夸克网盘分享了「000000我的笔记」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:https://pan.quark.cn/s/9589253580d6
链接:https://pan.baidu.com/s/1bFz8IX6EkFMWTfY9ozvVpg?pwd=deng
提取码:deng
b站视频:408-计算机网络-笔记分享_哔哩哔哩_bilibili
包含了408四门科目(数据结构、操作系统、计算机组成原理、计算机网络)
如果链接失效了,看看b站,或者私信我
链接: https://pan.baidu.com/s/1Qga8aMgcrVfCmrry68vqog?pwd=974t
提取码: 974t
互斥变量恒为1
申请成功就释放
PV操作总成对
同步首先是申请
生产消费要分开
拿走放入俩变量
有一个文件:
1、允许同时有多个进程进行读操作, 2、只允许一个进程同时进行写操作, 3、不能够在读操作的同时进行写操作。
请设计读进程和写进程,以满足上述条件。
semophore mutex=1; // 用于互斥操作count和写锁
semophore writeMutex = 1; // 写锁
int count=0; // 统计读者,当为0时,申请写锁或者释放写锁
semophore x=1 // 增加一个饥饿锁,防止writer饥饿,
void reader() {
P(x); // 申请 饥饿锁
// 操作count 和 写锁
P(mutex);
if(count==0){ // 如果为0就申请
P(writeMutex);
}
count++;
V(mutex);
V(x); // 释放 饥饿锁
read(); // 进行读操作
// 操作count 和 写锁
P(mutex);
count--;
if(count==0){ // 如果为0就释放
V(writeMutex);
}
V(mutex);
}
void writer(){
P(x); // 饥饿锁
P(writeMutex);
write();
V(writeMutex);
V(x); // 饥饿锁
}
45.(7分)三个进程P1、P2、P3互斥使用一个包含N(N>0)个单元的缓冲区。
P1每次用produce()生成一个正整数并用put()送入缓冲区某一空单元中;
P2每次用getodd()从该缓冲区中取出一个奇数并用countodd(统计奇数个数
P3每次用geteven()从该缓冲区中取出一个偶数,并用counteven(统计偶数个数
请用信号量机制实现这三个进程的同步与互斥活动,并说明所定义信号量的含义(要求用伪代码描述)。
分析:1个缓冲区,2个消费者,1个生产者
semophore mutex=1;
semophore empty=n;
semophore OddCount=0;
semophore EvenCount=0;
void P1(){
while(1){
int num = produce(); // 生成一个正整数
P(empty);// 看看满了没有
P(mutex); // 申请访问
put(); // 放入缓冲区
// 判断奇偶
if(num %2 == 0){
V(EvenCount);
}else{
V(OddCount);
}
V(mutex)// 释放
}
}
void P2(){
while(1){
P(OddCount); // 奇数-1
P(mutex);
getodd(); // 获取奇数
countodd();
V(empty); // 缓冲区空间+1
V(mutex);
}
}
void P3(){
while(1){
P(EvenCount); // 偶数-1
P(mutex);
geteven(); // 获取偶数
counteven();
V(empty); // 缓冲区空间+1
V(mutex);
}
}
8分)某银行提供1个服务窗口和10个供顾客等待的座位。
顾客到达银行时,若有空座位,则到取号机上领取一个号,等待叫号。
取号机每次仅允许一位顾客使用。当营业员空闲时,
通过叫号选取一位顾客,并为其服务。顾客和营业员的活动过程描述如下:
cobegin(){
process 顾客i()
{
从取号机获取一个号码;
等待叫号;
获取服务;
}
process营业员()
{
while(TRUE)
{
叫号;
为客户服务;
}
}
}coend
请添加必要的信号量和P、V(或wait()、signal())操作,实现上述过程中的互斥与同步。
要求写出完整的过程,说明信号量的含义并赋初值。
分析:
营业员:消费者(1个
顾客:产品——产品位置:10——取号机(互斥使用)
semophore mutex=1; // 互斥使用取号机
semophore cosumer=0; // 顾客数量
semophore empty=10; // 空位数量
semophore server=0; // 确保客户完成(实现同步
cobegin(){
process 顾客i()
{
// P(empty) 空位-1
// P(mutex) 互斥使用取号机
从取号机获取一个号码;
// V(mutex) 取完立即释放资源
// V(cosumer) 顾客数量+1
等待叫号; // V(server) 让快点来服务——同步关系 ✪ ✪ ✪
获取服务;
}
process营业员()
{
while(TRUE)
{
叫号; // P(cosumer) 顾客 -1
// V(empty) 空位+1
// P(server) 进行服务——同步关系 ✪ ✪ ✪
为客户服务;
}
}
}coend
博物馆最多可容纳500人同时参观,有一个出入口,该出入口一次仅允许一个人通过。
参观者的活动描述如下:
cobegin(){
参观者进程i()
{
进门;
...
参观;
...
出门;
}
}coend
请添加必要的信号量和P、V(或wait()、signal())操作,实现上述过程中的互斥与同步。
要求写出完整的过程,说明信号量的含义并赋初值。
分析: visitor(){} 参观者进程,出入口(互斥),博物馆(500人
参观者 – 入口(互斥) – 人数+1 – 出口(互斥) – 人数-1
semophore mutex=1; // 互斥访问【出入口】
semophore empty=500; // 空闲500人
参观者进程i()
{
// P(empty)空闲-1
// P(mutex)
进门;
// V(mutex)
...
参观;
...
// V(mutex)
出门;
// V(mutex)
// P(empty)空闲+1
}
系统中有多个生产者进程和多个消费者进程,共享一个能存放1000件产品的环形缓冲区(初始为空)。
当缓冲区未满时,生产者进程可以放入其生产的一件产品,否则等待;
当缓冲区未空时,消费者进程可以从缓冲区取走一件产品,否则等待。
要求一个消费者进程从缓冲区连续取出10件产品后,其他消费者进程才可以取产品。
请添加必要的信号量和P、V(或wait()、signal())操作,实现上述过程中的互斥与同步。
要求写出完整的过程,说明信号量的含义并赋初值。
semophore empty=1000; // 可以放1000个
semophore all =0; // 生成了多少
semophore mutex=1; // 互斥访问【环形队列缓冲区】
semophore x=1; // 互斥拿取【10个产品
void ProducerN(){
生产一个产品
P(empty) // 判断有没有空位
P(mutex)
把产品放入缓冲区
V(mutex)
V(all) // 产品+1
}
void CostumerN(){
P(x) // 互斥拿取
for( int i=0; i<10; i++){
P(all) // 判断有没有产品
P(mutex)
获取一个产品
V(mutex)
V(empty) // 空闲 +1
}
V(x) // 开锁
}
45.(9分)有A、B两人通过信箱进行辩论,每个人都从自己的信箱中取得对方的问题。
将答案和向对方提出的新问题组成一个邮件放入对方的邮箱中。
假设A的信箱最多放M个邮件,B的信箱最多放N个邮件。
初始时A的信箱中有x个邮件(0
A和B两人的操作过程描述如下:
A{ B{
while(TRUE){ while(TRUE){
从A的信箱中取出一个邮件; 从B的信箱中取出一个邮件;
回答问题并提出一个新问题; 回答问题并提出一个新问题;
将新邮件放入B的信箱; 将新邮件放入A的信箱;
当信箱不为空时,辩论者才能从信箱中取邮件,否则需要等待。
当信箱不满时,辩论者才能将新邮件放入信箱,否则需要等待。
请添加必要的信号量和P、V(或wait()、signal())操作,实现上述过程中的互斥与同步。
要求写出完整的过程,说明信号量的含义并赋初值。
分析:2个邮箱(互斥)并且限制大小、 2个都会被相互访问,
semophore Amutex=1; // 互斥访问A邮箱
semophore Bmutex=1; // 互斥访问B邮箱
semophore Aempty=M; // 可以放M个 这里出问题了 应该是M-x
semophore Bempty=N; // 可以放个N 这里出问题了 N-y
semophore Anum=0; // A 存在的邮件
semophore Bnum=0; // B 存在的邮件
A{
while(TRUE){
// P(Anum) 看看邮箱中是否有
// P(Amutex) 互斥访问
从A的信箱中取出一个邮件;
// V(Amutex)
// V(Aempty) 空位+1
回答问题并提出一个新问题;
// P(Bempty) 看看邮箱里面是否满了
// P(Bmutex) 互斥访问
将新邮件放入B的信箱;
// V(Bmutex)
// V(Bnum) 邮件+1
}
B{
while(TRUE){
// P(Bnum) 看看邮箱中是否有
// P(Bmutex) 互斥访问
从B的信箱中取出一个邮件;
// V(Bmutex)
// V(Bempty) 空位+1
回答问题并提出一个新问题;
// P(Aempty) 看看邮箱里面是否满了
// P(Amutex) 互斥访问
将新邮件放入A的信箱;
// V(Amutex)
// V(Anum) 邮件+1
}
答案
semaphore Full_A =x; //Full_A表示A的信箱中的邮件数量
semaphore Empty_A = M-x; //Empty_A表示A的信箱中还可存放的邮件数量
semaphore Full_B = y; //Ful1_B表示B的信箱中的邮件数量
semaphore Empty_B = N-y; //Empty_B表示B的信箱中还可存放的邮件数量
semaphore mutex_A = 1; //mutex_A用于A的信箱互斥
semaphore mutex_B = 1; //mutex_B用于B的信箱互斥
A{ B{
while(TRUE){ while(TRUE){
P(Full_A); P(Full_B);
P(mutex_A); P(mutex_B);
从A的信箱中取出一个邮件; 从B的信箱中取出一个邮件;
V(mutex_A); V(mutex_B);
V(Empty_A); V(Empty_B);
回答问题并提出一个新问题; 回答问题并提出一个新问题;
P(Empty_B); P(Empty_A);
P(mutex_B); P(mutex_A);
将新邮件放入B的信箱; 将新邮件放入A的信箱;
V(mutex_B); V(mutex_A);
V(Full_B); V(Full_A);
程中有3个并发执行的线程thread1、thread2和thread3,其伪代码如下所示。
//复数的结构类型定义
typedef struct{
float a;
float b;
}cnum
cnum x, y ,z; //全局变量
//计算两个复数之和
cnum add(cnum p, cnum q){
cnum s;
s.a=p.a+q.a;
s.b=p.b+q.b;
return s;
}
thread1(){
cnum w:
w=add(x, y);
...
}
thread2(){
cnum w;
w=add(y,z);
...
}
thread3(){
cnum w;
w.a = 1;
w.b = 1;
z=add(z,w);
y=add(y,w);
...
}
请添加必要的信号量和P、V(或wait()、signal())操作,要求确保线程互斥访问临界资源,
并且最大限度地并发执行。
分析:如果是一读一写或两个都是写,那么这就 是互斥关系。每一个互斥关系都需要一个信号量进行调节。
//复数的结构类型定义
typedef struct{
float a;
float b;
}cnum
cnum x,y,z; //全局变量
semophore YmutexR = 1; // 互斥读y (读锁
semophore YmutexW = 1; // 互斥写y (写锁
semophore Zmutex = 1; // 互斥访问z
//计算两个复数之和
cnum add(cnum p, cnum q){
cnum s;
s.a=p.a+q.a;
s.b=p.b+q.b;
return s;
}
thread1(){
cnum w:
P(Ymutex)
w=add(x, y);
V(Ymutex)
}
thread2(){
cnum w;
P(YmutexR) // 读锁
P(Zmutex)
w=add(y,z);
V(ZmutexR)
V(Ymutex)
}
thread3(){
cnum w;
w.a = 1;
w.b = 1;
P(Zmutex)
z=add(z,w); // 修改z
V(Zmutex)
P(YmutexR) // 读锁
P(YmutexW) // 写锁
y=add(y,w); // 修改y
V(YmutexW)
V(YmutexR)
}
43.(8分)有n(n≥3)位哲学家围坐在一张圆桌边,每位哲学家交替地就餐和思考。
在圆桌中心有m(m≥1)个碗,每两位哲学家之间有一根筷子。
每位哲学家必须取到一个碗和两侧的筷子后,才能就餐,进餐完毕,将碗和筷子放回原位,并继续思考。
为使尽可能多的哲学家同时就餐,且防止出现死锁现象,请使用信号量的P、V操作[wait()、signal()操作]描述上
述过程中的互斥与同步,并说明所用信号量及初值的含义。
// 信号量
semaphore bowl; //用于协调哲学家对碗的使用
semaphore chopsticks[n]; //用于协调哲学家对筷子的使用
for(int i=0; i<n; i++)
chopsticks[i]=1; //设置两个哲学家之间筷子的数量
bowl=min(n-1,m); //bowl ≤n-1,确保不死锁
CoBegin
while(TRUE){ //哲学家i的程序
思考;
P(bowl); //取碗
P(chopsticks[i]); //取左边筷子
P(chopsticks[(i+1)%n]); //取右边筷子
就餐;
V(chopsticks[i]);
V(chopsticks[(i+1)%n]);
V(bowl);
}
CoEnd
45、(7分)现有5个操作A、B、C、D和E,操作C必须在A和B完成后执行,操作E必须
在C和D完成后执行,请使用信号量的waitO、signalO操作(P、V操作)描述上述操作
之间的同步关系,并说明所用信号量及其初值。
semaphore A=0; // 控制A 和C 的执行顺序
semaphore B=0; // 控制B 和C 的执行顺序
semaphore C=0; // 控制C 和E 的执行顺序
semaphore D=0; // 控制D 和E 的执行顺序
A(){
完成A操作;
V(A); //实现A、C之间的同步关系
}
B(){
完成B操作;
V(B); //实现B、C之间的同步关系
}
C(){
// C 必须在A、B 都完成后才能完成
P(A);
P(B);
完成C操作;
V(C);
}
D(){
完成D操作;
V(D); //实现D、E之间的同步关系
}
E(){
// E 必须在C、D 都完成后才能完成
P(C);
P(D);
完成E操作;
}
要求学生使用swap指令和布尔型变量lock,实现临界区互斥。lock为线程间共享的变量。
lock的值为TRUE时线程不能进入临界区,为FALSE时,线程能进入临界区。
某同学编写的实现临界区互斥的伪代码如题
// 某同学编写的伪代码
Bool lock=FALSE; //共享变量
...
// 进入区
Bool key=TRUE
If (key== TRUE)
Swap(key, lock); //交换key和lock的值
...
// 临界区
...
Lock=TRUE; // 退出区
...
// newSwap0的代码
Void newSwap(bool*a, bool*b){
bool temp=*a
*a=*b;
*b=temp
}
(1)题45(a)图的伪代码中哪些语句存在错误?将其改为正确的语句(不增加语句条数)。
(2)题45(b)图给出了两个变量值的函数newSwap()的代码,是否可以用函数调用语句“newSwap(&key,&lock)”代替指令“swapkey,lock”以实现临界区的互斥?为什么?
while (key== TRUE)
Swap(key, lock); //交换key和lock的值
Lock=FALSE; // 退出区
第一问 :
第二问