zoukankan      html  css  js  c++  java
  • 进程同步和信号量

    进程的同步

    进程合作:多进程完成同一个任务

     

    实例1:

    司机              售票员

    while)true){          while)true){

    等待 启动车辆;           关门; 发送信号

       正常运行;           售票;

       到站停车;发送信号       等待 开门;

    }                }

    两个进程如何实现同步合作? 通过信号

    实例2:文档打印

    问题:如果进程之间完全不知道对方的存在,会产生怎样的错误?联系实际

     

     

    实际上的例子:生产者-消费者实例

    共享数据

      这些都是用户态

     

    生产者进程

    while(true){

      while(counter == BUFFER_SIZE)

         ; //阻塞  缓冲区满,生产者停

      buffer[in] = item;

      in = (in+1)%BUFFER_SIZE;

      counter++; //发信号让消费者走

    }

     

    消费者进程

    while(true){

      while(counter == 0)

       ; //阻塞  缓冲区空,消费者停

      item=buffer[out];

      out = (out-1)%BUFFER_SIZE;

      counter--; //发信号让生产者走

    }

     

    等待是进程同步的核心

     

    什么是进程同步?什么地方停,什么地方走?

    进程同步 事实上就是让进城走走停停,来保证多进程合作的合理有序

     

    只发信号还不能解决全部问题

    1.缓冲区满以后生产者P1生产一个item放入,会sleep

    2.有一个生产者P2生产一个item放入,会sleep

    3.消费者C执行1次循环,counter == BUFFER_SIZE - 1, 发信号给P1, P1 wake up。

    4.消费者C再执行1次循环,counter == BUFFER_SIZE - 2,P2不能被唤醒。

     

    counter无法区分有多少生产者进程,不仅需要唤醒进程(发送信号),还需要一个量用来记录睡眠进程的数量,来决定是否要发信号。

     

    这就引出了信号量

       

    从信号到信号量

    不只是等待信号,发信号? 对应睡眠和唤醒

    还能记录一些信息

    • 能记录有2个进程等待就可以了 可以使用优先队列或者是栈来存储
    • 1.缓冲区满,P1执行,P1 sleep,记录下一个进程等待 sem = -1
    • 2.P2执行,P2sleep,记录下两个进程等待   sem = -2
    • 3.C执行1次循环,发现两个进程等待,wakeup一个 wakeup P1 sem=-1
    • C再执行1次循环,发现一个进程等待,wakeup一个 wakeup P2 sem=0
    • C再执行1次循环4,发现没有进程等待,sem = 1
    • P3执行

    总结:

    什么时候减一?

    当有一个进程sleep,信号量-1

    什么时候加一?

    当发现信号量是负的,信号量+1,并且发信号wakeup; 如果发现信号量是正的,那么不发信号,累加信号量。

     

    问题:一种资源的数量是8,这个资源对应的信号量的当前值是2,说明():

    资源的数量是8,说明初始的sem是8,当前的信号量变为2,说明没有进程在等待等待这个资源。

     

    什么是信号量?信号量的定义

    信号量:1965年,由荷兰学者Dijkstra提出的一种特殊变量,量用来记录,信号用来sleep和wakeup

     

    struct semaphore

    {

       int value; //记录资料个数

       PCB *queue; //记录等待在该信号量上的进程

    }

    P(semaphore s); //消费资源

    V(semphore s); //产生资源

     

    P(semphore s)

    {

       s.value--;

       if(s.value < 0){

         sleep(s.queue); 

       }

    }

     

    问:V(s)的代码?

    V(semphore s){

      s.value++;

      if(s.value <= 0){

       wakeup(s.queue);

      }

    }

     

    Producer(item){

       P(empty);

       P(mutex);

       读入in;将item写入到in的位置上;

       V(mutex);

       V(full);

    }

     

    Constumer() {

       P(full);

       P(mutex);

       读入out;从文件out位置读出到item;打印item;

       V(mutex);

       V(empty);

    }

     

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

    int fd = open("buffer.txt");

    write(fd, 0, sizeof(int)); //写in

    write(fd, 0, sizeof(int)); //写out

     

    semaphore full = 0;

    semaphore empty = BUFFER_SIZE;

    semaphore mutex = 1;

     

    如何理解用信号量的生产者消费者代码?

    full用来判断是否为空,empty用来判断是否为满。通过P和V来睡眠和唤醒进程,并释放信号量。

     

    如何实现互斥访问?

    当进入缓冲区时,将mutex的值变为0,用完之后在释放。

     

     

  • 相关阅读:
    js中的计时器事件`setTimeout()` 和 `setInterval()`
    我的人生“意义”
    我活着的“形而上学”
    关于“我的”恶意
    不排他,与“我”的可能性
    【原创诗歌】自觉原理第十六章让你想照亮前程
    【原创诗歌】读书的梦:羡慕与期待
    【原创】楼兰老家
    【原创诗歌】青春咒语
    【原创】仓央嘉措,在心底活着
  • 原文地址:https://www.cnblogs.com/ACFLOOD/p/5451409.html
Copyright © 2011-2022 走看看