【操作系统】信号量 (生产者与消费者问题)

来源:互联网 发布:网络模块价格 编辑:程序博客网 时间:2024/04/27 22:46

1.信号量

进程往往需要并行执行,这样cpu利用率更高。正如数据库系统中的并行事务一样,一旦并行就会引来一些问题。在进程并行中,主要问题来自于共享资源的使用,比如共享内存或者共享文件等。这里有两个概念,访问共享资源的代码称为临界区。

信号量是dijkastra发明的一种用于同步进程的机制。每一种共享的资源都对应一个信号量s,s的初始值是共享资源的数目,为非负数。每一个信号量还要对应一个进程的指针,用于维护等待该资源的进程。

信号量上支持两种操作即,P和V操作。这两个操作都是原子操作,因此不可能同时被两个进程执行。

P操作:用于申请资源。其过程为,首先将信号量s的数值减去1,表明申请一个资源。如果s>=0,说明此次分配是成功的,那么进程可以继续执行;如果s<0,说明之前是s+1是小于1的,之前也就是0,说明没有可用资源,那么该进程会被阻塞并且被加入到等待队列中。

与之对应的是V操作

V操作:用于释放资源。其过程为,首先将信号量s的数值加1,表明释放一个资源。如果s>0,说明之前是大于-1的,即大于等于0的,说明没有等待的进程。而如果s<=0,说明之前一定小于0,那么有等待的进程,该进程释放资源以后,需要唤醒等待进程中的一个。

被唤醒的进程不需要再执行PV操作了。

(记忆PV操作信号量s的情况时,对于P操作,需要看看之前的值是否小于1,那么减一以后就是小于0,这个对应了等待的情况,所以有s小于0的case;对于V操作,需要看之前是否有小于0的情况,也就是加一小于1,即小于等于0的情况,说明之前有等待,需要唤醒)

2.互斥量

与信号量相关的另一概念是互斥量,可以看成是信号量的特例,即s初始化为1即可。假设现在有一段代码需要互斥,那么可以使用互斥量:

mutex = 1;P(mutex);临界区;V(mutex);
临界资源数目是1,如果要进入临界区,那么先要用P操作申请,使用完以后再执行V操作释放,需要时唤醒等待进程。

3.生产者与消费者问题:

这是多线程或者进程并发的经典问题,可以使用信号量解决。

这个问题的定义为,存在两种进程,生产者进程用于生产资源,消费者进程用于消费资源,资源存放在一个缓冲区中,生产者和消费者都需要与缓冲区打交道,生产者会放入,消费者会取出。显然这里有一些同步的条件:

(1)在同一时刻只能有一个进程进入缓冲区,因此需要一个互斥量;

(2)消费者只能在缓冲区中资源数目大于0时消费;

(3)生产者只能在缓冲区中资源数目不满时放入;

(2)和(3)需要利用到缓冲区中资源的数目,生产者需要得到剩余空间,可以使用empty信号量,初始化为N,即缓冲区的大小,因为开始时肯定全部空余;消费者需要得到产品数目信息,可以使用full信号量,初始化为0。那么进程函数为:

mutex = 1;full = 0;empty = N;produce(){    item = produceItem();    P(empty);    P(mutex);    put item;    V(mutex);    V(full);}consume(){    P(full);    P(mutex);    item = retrieveItem();    V(mutex);    V(empty);    consumeItem();}



原创粉丝点击