操作系统-理解信号量

信号量

信号量是一种常用的并发机制。基本原理:

两个或多个进程可以通过简单的信号合作,可以强迫一个进程在某个位置停止,直到它接收到一个特定的信号。任何复杂的合作都可以通过适当的信号结构得到满足。为了发信号,需要使用到一个信号量的特殊变量。要通过信号量s传送信号,进程必须执行semSignal(s)(V操作),要通过信号量s接收信号,进程必须执行原语semWait(s)(P操作);若相应的信号未被发出,则阻塞进程,直到发送完为止。

以上是从书中摘录出来的有关信号量的基本原理。
实际上,我理解的信号量应该像是一个计数器更准确,对于这个计数器我们可以定义三个操作为了达到互斥的效果。

  1. 可以将该信号量也就是计数器初始化为一个非负整数
  2. P操作使信号量减一;若值减为负数,则阻塞当前申请的进程,否则进程继续执行。
  3. V操作使信号量加一;若值小于等于0,则将当前阻塞进程接触阻塞。

我们假设一个场景来解释以上定义:
比如说,一件自习室里有十个座位。那么我们用s表示计数器用来表示当前教室的可用资源也就是座位。
现在来了一个同学,想要进入自习室自习,他发现这个计数器为10,说明可以进入,所以它向管理员申请进入,并且得到许可,可以进入自习室自习。此时,当然计数器就变为9了。
后来,又陆陆续续来了几个同学,直到计数器变成了0。此时再来这个教室申请座位的同学发出申请之后就会被阻塞,因为该教室已经没有座位了,意味着他需要在门口一直等。
等了一会儿之后,有一个同学出来了,计数器此时由于可用资源多一,所以将计数器加一,此时计数器由0至1,也就意味着,此时在门口等待的这位同学可以进入教室了。

实际上在操作系统中,同学就好像进程,教室的座位就像进程所需临界资源。计数器就是我们所说的信号量。
下面我们来理理:
信号量是一个计数器,用来记录进入该临界资源的进程数。若信号量s小于等于0,说明此时没有可用的临界资源,那么此时在向该临界资源申请资源的进程就会被阻塞。如果一旦有进程释放该临界资源,那么信号量s就会加1,此时被阻塞的进程就会解除阻塞,并且成功申请到临界资源。

我们将以上动作中,申请临界资源,信号量减一的动作-称为P操作。
释放临界资源,信号量加一的动作称为-V操作。
并且P V操作都是原子性

信号量s表示的意义:

  • s>0:表示当前可用资源的个数
  • s<0:当前等待的进程个数
  • s=0:当前无可用资源

下面给出原语的定义:

struct semaphore{
    int count;
    queueType queue;
};
void semWait(semaphore s)
{
    s.count--;
    if(s.count<0)
    {
        /*把当前进程插入阻塞队列*/
        /*阻塞当前进程*/
    }
}

void semSignal(semaphore s)
{
    s.count++;
    if(s.count<=0)
    {
        /*把进程从阻塞队列中移除*/
        /*把进程插入就绪队列*/
    }
}

二元信号量

下面给出对二元信号量的定义:

struct binary_semaphore{
    enum 
    {zero,one}; value;
    queueType queue;
};
void semWait(binary_semaphore s)
{
    if(s.value==one)
        s.value=zero;
    else
    {
        /*把当前进程插入队列*/
        /*阻塞当前进程*/
    }
}
void semSignal(binary_semaphore s)
{
    if(s.queue is empty())
        s.value=one;
    else
    {
        /*把进程从阻塞队列中移除*/
        /*把进程插入就绪队列*/
    }
}
  • 二元信号量可以初始化0或1;
  • P操作检查信号量的值,若值为0,则执行P操作的进程就会被阻塞。若值为1,就将值改为0,并继续执行该进程。
  • V操作是检查是否有进程在该信号上受阻。若有进程受阻,则通过V操作的进程将会被唤醒;若没有进程受阻,则值设为1。
    理论上,二元信号量更易实现,为了区分这两种信号量,非二元信号量被称为计数信号量(更验证了我们前面的理解)。

互斥锁:互斥锁是与二元信号量相关的一个概念,下面做解释:

互斥是一个编程标志位,用来获取和释放一个对象。当需要的数据不能被分享或处理,进而导致在系统中的其他地方不能同时执行时,互斥被设置为锁定,用于阻塞其他程序使用数据。当数据不再需要或程序运行结束时,互斥被设定为非锁定。

互斥与二元信号量的区别:为互斥量加锁的进程和为互斥量解锁的进程必须时同一个进程。相比之下,可能由某个进程对二元信号量进行加锁操作,由另一个进程为其解锁。(其实,在一些文献和教材中,互斥锁与二元信号量并未区别。)

强、弱信号量

不论是二元信号量还是级数信号量,都需要一个队列来保存当前正在等待的进程,那么就产生一个问题,进程按照什么顺序从队列中移除?
最公平的策略是先进先出:被阻塞时间最久的先从队列中移除。采用这一种策略的称为强信号量,而没有规定进程从队列中移除顺序的信号量称为弱信号量。强信号量保证不会饥饿,而弱信号量则无法保证。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值