秦点点丶

秦小晋不弱智智障反而美丽可爱啦!

导航

信号量

                 信号量的取值可以为0(表示没有保存下来的唤醒操作),可以为正值(表示有一个或者多个唤醒操作)。

      两个操作:down操作:若该值大于0,将其值减1(即用掉一个保存的唤醒信号);若该值为0,则进程将睡眠,并且down操作并未结束!检查数值,修改变量值以及可能发生的睡眠操作均作为一个单一的,不可分割的原子操作完成。保证一旦一个信号量操作开始,则在该操作完成或者阻塞之前,其他进程均不允许访问该信号量。所谓原子操作,是指一组相关联的操作要么都不间断地执行,要么都不执行

      Dijkstra原来的论文中,他分别使用名称是P和V而不是down和up,而在操作系统概念一书中,使用wait(),signal()

       信号量的实例:

      用信号量解决生产者-消费者问题

 1 #define N 100             /*缓冲区中槽的数目*/
 2 typedef int semaphore;    /*信号量是一种特殊的整形数据*/
 3 semaphore mutex = 1;      /*控制对临界区的访问*/
 4 semaphore empty = N;      /*计数缓冲区的空槽数目*/
 5 semaphore full = 0;       /*计数缓冲区的满槽数目*/
 6 
 7 
 8 void producer(void)
 9 {
10     int item;
11     
12     while(true){                        /*TRUE是常量1*/
13         item = produce_item();          /*产生放在缓冲区中的一些数据*/
14         down(&empty);                   /*将空槽数目减1*/
15         down(&mutex);                   /*进入临界区*/
16         insert_item(item);              /*将新数据项放到缓冲区中*/
17         up(&mutex);                     /*离开临界区*/
18         up(&full);                      /*将满槽的数目加1*/
19     }
20 }
21 
22 void consumer(void)
23 {
24         int item;
25     
26     while(true){                        /*无限循环*/
27         down(&full);                    /*将满槽数目减1*/
28         down(&mutex);                   /*进入临界区*/
29         item = remove_item();           /*从缓冲区中取出数据项*/
30         up(&mutex);                     /*离开临界区*/
31         up(&empty);                     /*将空槽数目加1*/
32         consume_item(item);             /*处理数据项*/
33     }
34 }

     该方案使用了三个信号量:full,用来记录充满缓冲槽的数目,初值为0;empty,记录空的缓冲槽数目,初值为N;mutex,用来确保生产者和消费者不会同时访问缓冲区,初值为1,保证同时只有一个进程可以进入临界区。如果每个进程在进入临界区前执行一个down操作,并在刚刚退出时执行一个up操作,就能实现互斥

    该方案中,实际上是通过两种不同的方式来使用信号量,信号量mutex用于互斥,保证任一时刻只有一个进程读写缓冲区和相关变量。而信号量full和empty用来保证某种事件的顺序发生或者不发生,用于实现同步。

    

posted on 2014-12-16 21:24  秦点点丶  阅读(354)  评论(0编辑  收藏  举报