zoukankan      html  css  js  c++  java
  • 操作系统:进程间的相互作用(多线程基础)

    进程间的相互作用

    两种相互作用

    同步

    多个相关进程在执行次序上的协调

    制约关系:直接制约。

    如图所示:一个进程在执行操作的时候,另一个进程必须等待,体现在次序上的等待和协调,并不争夺临界资源。

    互斥

    多个进程因为争夺临界资源相互排斥执行的过程称为进程的互斥

    临界资源:也称为独占资源,是指在一段时间内只允许一个进程访问的资源。

    制约关系:间接制约。 

    解决并发进程的问题

    一.加锁法——自旋锁

    思路:

      设置一个共享变量W (锁) ,初值为0。当一个进程想进入其临界区(进程中涉及临界资源的程序段)时,它首
    先测试这把锁:如果锁的值为0,则进程将其置为1并进入临界区。若锁已经为1,则进程等待直到其变成0。
    实现:
      加锁原语:LOCK(W) :L: if W=1 then goto L else W=1;
      解锁原语:UNLOCK(W):W=0;

    二.信号量和PV操作

    信号量:
    说明:
        表示资源的实体——是一个与队列有关的整型变量。

    说明:其值只能通过初始化操作和P、V操作来访问。

    类型:
      公用信号量:用于进程间的互斥,初始值通常为1.
      私有信号量:用于进程间的同步,初始值通常为0或N .
    P操作(Wait操作):
    proberen——检查。意味着请求分配一个单位资源

    S=S-1
     if(S<0)
     {
        //调用进程被阻塞,进入S的等待队列
     }

     
    V操作(Signal操作):
    荷兰语“verhogen”——“增量”之意,意味着释放/增加一个单位资源

    S=S+1;
    if(S<=0)
    {
        //从S的等待队列中唤醒一个进程使其进入就绪状态
    }


    使用PV实现互斥

    使用PV实现进程同步

    IPC经典问题

    生产者消费者问题(有限缓存问题)

    描述:生产者和消费者共享n个缓冲区,生产者生产产品放入缓冲区,消费者从缓冲区中取产品消费。请写出能够正确反映它们逻辑关系的代码

      

    两个隐含条件:

      1.消费者和生产者数量不固定。

      2.消费者和生产者不能同时使用缓存区。

    行为分析:

      生产者:生产产品,放置产品(有空缓冲区)。

      消费者:取出产品(有产品),消费产品。

    行为关系:

      生产者之间:互斥(放置产品)

      消费者之间:互斥(取出产品)

      生产者与消费者之间:互斥(放/取产品) 同步(放置——取出)

    信号量设置:

      semaphore mutex =1;//互斥

      semaphore empty=n;//空闲数量

      semaphore full=0;//产品数量

    伪代码:

    semaphore mutex=1 //互斥
    semaphore empty=n //缓冲区空闲数
    semaphore full=0 //产品数量
    
    生产者:
    while(1)
    {
        product; //生产
        p(empty);
        p(mutex);
        add to buffer;//放置产品
        v(mutex);
        v(full)
    }
    
    消费者:
    while(1)
    {
        p(full);
        p(mutex);
        get from buffer;//取出产品
        v(mutex);
        v(empty)
        conseume; //消耗
    }

     读者写者问题

    描述:一个数据对象(文件、记录)可以为多个并发进程共享。其中有的进程只需要读其中的内容,我们称为“读者”;有的进程负责更新(读写)其中内容,我们称为“写者”。

       规定:“读者”可以同时读取共享数据对象;“写者不能和其它任何进程同时访问共享数据对象

      

    行为分析:

      Ø读进程的行为:

    • 系统中会有多个读进程同时访问共享数据。
    • 我们可以将它们分为三类:第一个进入的读进程(占有资源),最后一个离开的读进程(释放资源)和其他读进程。
    • 我们需要设置一个计数器readnum来记录读进程的数目。

      Ø写进程的行为:排他性的使用资源。

      Ø确定同步与互斥关系:

        读者-读者:互斥访问readnum

        读者-写者:互斥访问Data

        写者-写者:互斥访问Data

      Ø确定临界资源:

        Data,readnum

    信号量设置:

     int readnum=0;

     semaphore mutex=1;//公用信号量,用于readnum的互斥。

     semaphore write=1;//公用信号量,用于Data访问的互斥。

    伪代码:

    int readnum=0; //计数,用于记录读者的数目
    semaphore mutex=1; //公用信号量,用于readnum互斥
    semaphore write=1; //公用信号量,用于Data访问的互斥,
    
    读者:
    p(mutex) //对readnum互斥
    readnum++;
    if(readnum==1)
        P(write) //申请使用data资源
    V(mutext) //释放readnum
    
    reading;
    
    p(mutex) //对readnum互斥
    readnum--;
    if(readnum==0)
        V(write) //释放data资源
    V(mutext) //释放readnum
    
    写者:
    //P(mutex)
    P(write) //write本身已经互斥
    writing;
    v(wirte) 
    //V(mutex)

     理发师问题  

    描述:理发店有一位理发师和一把理发椅。如果没有顾客,则理发师在理发椅上睡觉;当有顾客到达时,如理发师在睡觉则唤醒他理发,如果理发师正忙着理发,则坐在椅上等待。   编写程序实现理发师和顾客行为的正确描述。 

      

    行为分析:

      Ø理发师行为:睡觉、理发。没有顾客睡觉,有顾客理发。

      Ø顾客行为:理发或等待。

      Ø相互作用:

        理发师与顾客之间:同步

        顾客与顾客之间:无

    信号量设置:

      semaphore customers=0; //customers表示等候理发的顾客数量

      semaphore barbers=0;  //barbars表示等候顾客的理发师数量

    伪代码:

    semaphore customers=0; //customers表示等候理发的顾客数量
    semaphore barbers=0;  //barbars表示等候顾客的理发师数量
    
    理发师代码:
    while(1)
    {
        p(customers) //检查是否有顾客
        v(barbers)  //告诉顾客有发型师
        Cut_hair();
    
    }
    
    顾客代码:
    V(customers)
    p(barbers);
    Get_hair();

    这里主要体现了进程的同步。如有疑问,请看信号量介绍的同步实现。

    增加条件:理发店有n把椅子,顾客到达时如果理发师空闲则理发,如果理发师忙,则看椅子上是否还有空位置,有空位置等待,没有空位置就离开。

    伪代码:

    semaphore customers=0; //customers表示等候理发的顾客数量
    semaphore barbers=0;  //barbars表示等候顾客的理发师数量
    int waiting =0;     //等待人数
    semaphore mutex=1;  //用于waiting的互斥
    
    
    理发师进程:
    while(1)
    {
        p(customers) //检查是否有顾客
            P(mutex);
                waiting=waiting-1;
            v(mutex);
        v(barbers)  
        Cut_hair();
    
    }
    
    顾客进程:
    P(mutex) //占空椅子的操作是互斥的,即一个一个占
    if(waiting<n) then  //如果座位未满
    {
        waiting=waiting+1;
        V(mutex);
        V(customers);
        P(barbers); //检测是否有理发师
        Get_haircut();
    }
    else
    {
        V(mutex); //表示座位已经满了
    }

    使用PV操作的注意事项

       1.P、V操作(对同一信号量)总是成对出现的;互斥操作时他们处于同一进程中;同步操作时他们处于不同进程中。

       2.信号量初始值的设置和P、V操作的位置及次序是关键,要十分小心的设置,一定要保持正确的逻辑关系和较高的执行效率。

  • 相关阅读:
    【体系结构】Oracle 11g体系结构总览
    【RMAN】RMAN初探
    【RAC】Oracle 11g 启动、停止实例和RAC数据库
    【RAC】Oracle 11g RAC安装及配置(三)
    【RAC】Oracle 11g RAC安装及配置(二)
    【RAC】Oracle 11g RAC安装及配置(一)
    【Linux】mount、umount命令
    领域模型(DomainModel)与视图模型(ViewModel)
    ASP.NET MVC与ASP.NET WebForm
    Visual Studio 2017 插件扩展
  • 原文地址:https://www.cnblogs.com/MrSaver/p/6147437.html
Copyright © 2011-2022 走看看