OS-互斥和同步

操作系统作业-并发性:互斥和同步

 

1. 什么是临界资源、临界区,临界区的使用原则有哪些?

进程间在竞争控制中会面临互斥问题。假设两个或者更多的进程需要访问一个不可共享的资源,如打印机,在进程的执行过程中,每个进程都给该I/O设备发命令,接收状态信息,发送数据和接受数据,则这类资源称为临界资源。

使用临界资源的那部分程序称为程序的临界区。

临界区主要解决的是互斥问题,互斥问题的要求可总结为:空闲让进,忙则等待,有限等待,让权等待。同时,这也是对于临界区使用的原则,具体内容如下:

  1. 实施强制互斥:在与相同资源或共享对象的临界区有关的所有进程中,一次只允许一个进程进入临界区;
  2. 一个在非临界区停止的进程不能干涉其他进程
  3. 绝不允许出现需要访问临界区的进程被无限延迟的情况,即不会死锁或饥饿;
  4. 没有进程在临界区中时,任何需要进入临界区的进程必须能够立即进入;
  5. 对相关进程的执行速度和处理器的数量没有任何要求和限制;
  6. 一个进程驻留在临界区中的时间必须是有限的。

 

2. 简述信号量的含义及作用。

信号量的含义:用于进程间传递信号的一个整数值。在信号量上只可进程初始化、递减和递增这三种操作,且操作都是原子操作。

信号量的作用:解决互斥问题,在两个或多个进程通过信号量进行合作时,可以强迫一个进程在某个位置停止,直到它接收到一个特定的信号。信号量的三种操作中,递减操作用于阻塞一个进程,递增操作用于解除一个进程的阻塞。

 

3. 请用P、V操作描述下列过程


 

//司机
void driver(){
    while (true)   {
        semWait(door);     //收到关门信息,开始开车
        /*正常运行*/;
        semSignal(stop);    //到站停,释放门这个资源
    }
}

//售票员
void conductor(){
    while (true){
        semSignal(door);    //发送信号:关门
        /*售票*/;
        semWait(stop);      //接收司机释放的到站停信息
        /*开门*/;
    }
}

4.   图书馆有N个座位,一张登记表,要求(1)阅读者进入时登记,取得座位号;(2)出来时注销。请用P、V操作描述一个读者的使用过程。

//图书馆没有座位就等待
semaphore s = N , M = 1;    //s可用座位,M=1表示无人在使用

void lib1(){
    while(true){
        semWait(s);
        semWait(M);
        /*登记*/;
        semSignal(M);   
        /*阅读*/;
        semWait(M);
        /*注销*/;
        semSignal(M);
        semSignal(s);
    }
}

//图书馆没有座位就离开
int COUNT = 100;
semaphore M = 1;
void lib2(){
    semWait(M);
    if(COUNT == 0){
        semSignal(M);
        return;
    }
    COUNT = COUNT - 1;
    /*登记*/;
    semSignal(M);
    /*阅读*/;
    semWait(M);
    /*注销*/;
    semSignal(M);
    semWait(M);
    COUNT = COUNT + 1;
    semSignal(M);
    return;
}

5.    4个并发执行的进程P1、P2、P3和P4合作解决数据计算问题:Y(i)=X(i)2+X(i)3.

(1)   P1不断产生随机数并放入到缓冲区A中;

(2)   P2、P3分别读取缓冲区A中的数据并计算其平方值、立方值,然后分别放入缓冲区B、C中;

(3)   P4读取缓冲区B、C中的数据,将其相加,并输出;

(4)   缓冲区A、B、C的容量为1。

semaphore emptyA = 1,emptyB = 1,emptyC = 1; //初始A,B,C为空
semaphore fullA = 0,fullB = 0,fullC = 0 , readA = 0;//readA=0,不读     

void p1(){
    while(true){
        /*产生随机数*/;
        semWait(emptyA);            //接收到A空的信号
        /*将随机数放入缓冲区A*/;
        semSignal(fullA);           //写入后A为满
    }
}

void p2(){
    while(true){
        semWait(fullA);             //接收到A已写入
        /*从A取数据*/;
        semSignal(readA);           //发信号让B读A
        /*计算平方值*/;
        semWait(empytB)             //接收到B为空的信号
        /*平方值放入缓存区B*/;
        semSignal(fullB);           //写入B
    }
}


void p3(){
    while(true){
        semWait(readA);             //等p2读了数据,p3接收到readA信号再读  
        /*从A取数据*/;
        semSignal(emptyA);          //释放A的资源
        /*计算立方值*/;
        semWait(emptyC);            //接收到C为空的信号
        /*立方值放入缓存区C*/;  
        semSignal(fullC);           //写入C
    }
}

void p4(){
    while(true){
        semWait(fullB);             //接收到B满的信号
        /*取缓冲区B数据*/;
        semSignal(emptyB);          //取出B,发送empytB信号
        semWait(fullC);             //接收到C满的信号
        /*取缓冲区C数据*/;
        semSignal(emptyC);          //取出C,发出emptyC的信号
        /*计算B+C的数据*/;
        /*数据B+C 输出*/;
    }
}

6.   桌上有一空盘,最多允许存放一只水果。爸爸可向盘中放一个苹果或放一个桔子;儿子专等吃盘中的桔子,女儿专等吃苹果。用P、V操作实现爸爸、儿子、女儿三个并发进程的同步。

semaphore P=1;

int plate = 0;                      //plate=0时,盘子为空 
int put = 0;                        //put=0 放桔子  put=1 放苹果                 

void father(){
    while(true)
        if(plate == 0){             //如果盘子为空
            semWait(P);             //得到盘子的使用权
                if (put == 0){      //放桔子
                    semSignal(S0);  //释放专吃桔子的盘子使用权
                }                   
                else{               //放苹果  
                    semSignal(S1);  //释放专吃苹果的盘子使用权
                }             
        }
        else{
            return;
    }
}

void son(){
    while(true){
        semWait(S0);                //等到盘子放桔子的信号
        /*从盘中拿桔子*/;   
        semSignal(P);               //释放盘子的使用权
        /*吃桔子*/;
    }
}

void daughter(){
    while(true){
        semWait(S1);                //等到盘子放苹果的信号
        /*从盘中拿苹果*/;   
        semSignal(P);               //释放盘子的使用权
        /*吃苹果*/;
    }
}

7.      用P、V原语实现东西向单行道上车辆的正确行驶,要求:(1)当有车自东向西方向(或自西向东方向)行驶,另一方向上的车辆须等待;(2)同一方向上的车可以连续通过;(3)当某一方向上已经没有车辆在单行道上行驶时,另一方向上的车辆即可以进入单行道。

int e_wcount, w_ecount;
semaphore x1 = 1,x2 = 0,wsem = 1;

void e_w(){
    while ((true){
        semWait(x1);
        e_wcount++;
        if(e_wcount == 1){
            semWait(wsem);
        }
        semSignal(x1);
        /*通过*/;
        semWait(x1);
        e_wcount--;
        if (e_wcount == 0){
            semSignal(wsem);
        }
        semSignal(x1);
    }  
}

void w_e (){
    while (true){
        semWait(x2);
        w_ecount++;
        if (w_ecount == 1){
            semWait(wsem);
        }
        semSignal(x2);
        /*通过*/;
        semWait(x2);
        w_ecount--;
        if (w_ecount == 0){
            semSignal(wsem);
        }
        semSignal(x2);
    }
}

8.   某寺庙,有小、老和尚若干,有一水缸,由小和尚提入水缸供老和尚饮用。水缸可容10桶水,水取自同一井中。水井径窄,每次只能容一个水桶取水,水桶总数为3个。每次入水、取水仅为1桶,且不可同时进行。试给出有关老和尚从缸取水和小和尚打水、入水的算法描述。(感觉这个题,描述得很有问题,不好)

int tong = 3,vatWater = 10,haveWater=0; 

void little(){
    while(true){
        semWait(vatWater);      //看缸里水有多少
        semWait(tong);          //等待空闲的桶
        semWait(s1);            //取打水使用权
        /*打水*/;
        semSignal(s1);          //释放打水使用权
        semWait(s2);            //取入水缸使用权(入水)
        /*入水*/;
        semWait(s2);            //释放水缸使用权
        semSignal(tong);           //释放桶的使用权
        semSignal(haveWater);   //打了水了
    }
}

void old(){
    while(true){
        semWait(haveWater);     //呗小和尚告知有水了
        semWait(tong);          //有桶了
        semWait(s1)             //取水缸使用权
        /*取水*/;
        semSignal(s1);          //释放水缸使用权
        semSignal(tong);        //释放桶的使用权
        semSignal(vatWater);    //缸里的水被打了,告知小和尚
    }
}

 

9.   参考读者优先问题的代码,分析读者进程中的if (readcount==1) P(wsem) 是否可以放到紧跟的V(x)语句后?给出可以或不可以的理由。类似的,分析if (readcount==0) V(wsem) 是否可以放到紧跟的V(x)语句后

if (readcount==1) P(wsem)不能放到紧跟的V(x)语句后,因为P(x)和V(x)保证了再这两条语句中间,不能有其他的进程来更改readcount的值。

如果将if (readcount==1) P(wsem)放到紧跟的V(x)语句后,这期间为非原子操作,readcount的值可能被另一个进程更改为0,从而造成错误。

 

if (readcount==0) V(wsem)不能放到紧跟的V(x)语句后,理由跟上一问一样。

如果将if (readcount==0) V(wsem)放到紧跟的V(x)语句后,这两条语句之间为非原子操作,从而导致readcount的值可能被其他进程修改为1,导致出错。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值