关于计算机操作系统中信号量应用问题以及“记录型信号量”解决生产者消费者问题案例的理解...

一:关与记录型信号量,

里面主要是由一个wait操作和signal操作,利用他来实现的一般就是进程的互斥了。
semaphore mutex=1;
    P1(){
        while(1){
            wait(mutex);##--
            临界区;
            signal(mutex);##++
            剩余区;
        }
    }
      P2(){
        while(1){
            wait(mutex);##--
            临界区;
            signal(mutex);##++
            剩余区;
        }
    }
##  这里有两个进程1,2都争用一个临界区,这个时候又要实现进程的并行,所以可以用到记录型信号量来实现,当然还有其他的方法这里只对记录型信号量来讨论互斥。

复制代码

P1 和P2的实现过程是这样的:(通俗篇)

S1:P1,P2没人知道谁先执行谁后执行,这里面因素有很多,微弱的电流,暗物质,巴拉巴拉一大堆客观因素(暂且称之为小弟)。。。
   但是有一点是聪明的人类定义的逻辑,那就是mutex信号量(互斥信号量),它就如同这众多因素里面的老大,
   可以扭转整个局面。此时呢,它初始值是1;我们定义时1就是允许执行的。
   
S2:所以此时,总要有一个先执行(在同时mutex=1的前提下,谁的优先级不由老大决定了,下面小弟们都蠢蠢欲动,决定各自为政,
都想决定大事儿,此时我们就睁只眼闭只眼"随机"去吧,),假设现在我们得知是P1先被决定为先执行了,此时mutex=0了。P1被安排了,
可以自己独享临界资源了。

S3:由于计算机中执行速度是"超速度的",所以此时P2()怎么的也执行了wait(mutex)了,所以此时的mutex值就从0变为-1了,此时状态是,
临界资源被P1占用着,考虑到分配的原子性,这边我们逻辑上通过mutex的值对应分配关系,此时逻辑上是P2已经就绪状态,就等临界
资源空闲立马执行了,所以此时mutex=-1反应的一个逻辑状态是:P1在使用临界资源,在临界区执行着(ing时态),
P2处于一切就绪等待("被分配到阻塞队列中了")进入临界区状态,此时需要mutex决定P2的进入与否,也就是需要P1的唤醒了。

S4:终于要P1享用完了,美滋滋,开开心心的按下结账按钮,也就是执行到了signal(mutex)了,此时呢由于P1是彻底释放资源了,所以执行
signal(mutex)操作后mutex=0("取值范围mutex=-1,0,1"),因为P2已经进入了就绪等待状态("已经在阻塞队列中了"),一但mutex的值增
加了,就会立马被唤醒直接进入临界区操作,不会再次执行P操作(wait(mutex)),所以此时mutex=0,就直接变成了P2在临界区了,
P1已经出去了。接着P2临界区执行完毕,执行V操作(signal(mutex)),此mutex=1了,此时二者均没被使用,结束一个完整的流程。


特殊情况: 当然如果你还要追根问底,探索其他情况,比如说S4步骤开始P1执行完了,可是谁知道这个进程背后程序员设计的程序会不会紧接着
一行写到又要调用同一个临界资源呢,所以这时P2很不幸,又要被P1欺负,争抢,首先我们已经知道此时的"mutex=0",由于此时P1是刚执完的,
不像P2是经历过mutex=-1的人,已经早早的排起了队("阻塞队列"),P1此时刚出来门口,此时又反悔想回去再退掉刚刚买的手机,
但是他此时也要按规矩去排队,而且一定是在P2后面(P2得意了一回,哈哈哈)。此时由于P2是被P1出来这个动作唤醒的,
所以直接进去就行了(不会再回头执行P操作,mutex不会被P2改变此时,此时的mutex=0,是被P1的V操作改变的),
此时P1的V操作执行了,将"mutex有变成了-1",那么就标志着P1排上队了("阻塞队列"),屋("临界区")里面有人。
复制代码

关于mutex的总结
mutex=-1,0,1

当mutex=1时,两个互斥的进程都没有进入临界区;

当mutex=0时;两个互斥的进程有一个进入了临界区,但是没发生争执;

当mutex=-1时,两个互斥的进程有一个在临界区,有一个不在临界区,但是至少那个不在临界区的进程争执过,将mutex变成了-1,
那么同时他没争赢就会进入阻塞队列中,当代被唤醒立即进入




<<<不知道了流程的可以从参看我上面的例子,同时也方便理解,不求一知半解,但求追根问底!!!
复制代码

二: 生产者,消费者问题

生产者消费者问题是这样的:

#include<pushAPoP.h>
int in = 0, out = 0;
int full = 0, empty = n, mutex = 1;
item buffer[n];

producer {
    while( true ) {
        wait( empty );  // 等待缓冲区有空闲位置,与互斥锁位置时绝对的,必须放在前面,包含锁。
        wait( mutex );  // 保证在product时不会有其他线程访问缓冲区

        // product
        buffer.push( full, in );  // 将新资源放到buffer[in]位置 
        in = ( in + 1 ) % n;

        signal( mutex );  // 唤醒的顺序可以不同
        signal( full );  // 通知consumer缓冲区有资源可以取走
    }
}

consumer {
    while( true ) {
        wait( full );  // 等待缓冲区有资源可以使用
        wait( mutex );  // 保证在consume时不会有其他线程访问缓冲区

        // consume
        buffer.pop( out );  // 将buffer[out]位置的的资源取走
        out = ( out + 1 ) % n;

        signal( mutex );  // 唤醒的顺序可以不同
        signal( empty );  // 通知缓冲区有空闲位置
    }
}



复制代码

伪代码参考:blog.csdn.net/liushall/ar…

转载于:https://juejin.im/post/5c306fdff265da61620d8ac1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值