进程同步 订阅
进程同步:在多道程序环境下,进程是并发执行的,不同进程之间存在着不同的相互制约关系。 [1] 展开全文
进程同步:在多道程序环境下,进程是并发执行的,不同进程之间存在着不同的相互制约关系。 [1]
信息
外文名
Process Synchronization
所属范围
计算机技术
中文名
进程同步
进程同步同步的概念
我们把异步环境下的一组并发进程因直接制约而互相发送消息、进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。具有同步关系的一组并发进程称为合作进程,合作进程间互相发送的信号称为消息或事件。 如果我们对一个消息或事件赋以唯一的消息名,则我们可用过程 wait (消息名)  表示进程等待合作进程发来的消息,而用过程 signal (消息名) 表示向合作进程发送消息。 [2] 
收起全文
精华内容
下载资源
问答
  • 本文是对进程同步机制的一个大总结(9000+字吐血总结),涵盖面非常的全,包括了进程同步的一些概念、软件同步机制、硬件同步机制、信号量机制和管程机制,对每种机制结合代码做了详细的介绍,并且对琐碎的知识点和...
  • 进程同步练习题 1. 在公共汽车上,司机和售票员的工作流程如图所示。为保证乘客的安全,司机和售票员应密切配合协调工作。请用信号量来实现司机与售票员之间的同步。
  • 进程同步实验报告

    2018-04-02 19:09:06
    (1)了解操作系统进程同步的基本概念和准则。 (2)理解信号量机制及P、V操作含义。 (3)了解经典进程同步问题,掌握信号量方法解决进程同步问题的方法。 包括实验目的,截图,心得体会,代码
  • Java实现进程同步

    2018-09-27 12:08:57
    进程同步,用Java实现,源代码。 生产者-消费者问题 生产者-消费者
  • 本篇文章主要介绍了Python实现进程同步和通信的方法,详细的介绍了Process、Queue、Pipe、Lock等组件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • linux父子进程同步及进程通讯,恰同学少年,风华正茂,挥斥方遒
  • 解决进程同步中熟睡的理发师问题 包含源代码与输出结果
  • 实现了三个进程同步协作模拟打印过程,三个进程P1,P2,P3 和两个缓冲区L1,L2。P1用于将要打印的文档存入L1,P2负责将L1文档放入L2,最后P3取出打印。 课程实验时所作,内含实验报告。
  • 进程同步的几种机制

    2015-08-26 21:29:38
    本讲将介绍进程间的两种主要关系——同步与互斥,然后着重讲解解决进程同步的几种机制。
  • 操作系统实验之进程同步,里面已经包含报告,只需要写个人感想即可
  • 主要介绍了Python多进程同步简单实现代码,涉及Python基于Process与Lock模块运行进程与锁机制实现多进程同步的相关技巧,需要的朋友可以参考下
  • 大连理工大学操作系统大作业, 进程同步与互斥 生产者与消费者问题
  • Experiment03_父子进程同步与子进程重载(Linux)
  • 进程同步与互斥

    2013-12-19 10:17:14
    有关于进程同步于互斥的C语言实现,希望对你们有帮助!
  • 进程同步实验C语言代码
  • 实验三进程同步实验 一实验任务 1掌握操作系统的进程同步原理 2 熟悉 linux 的进程同步原语 3 设计程序实现经典进程同步问题 二实验原理 1PV 操作 PV 操作由 P 操作原语和 V 操作原语组成 原语是不可中断的过程 对...
  • 操作系统4————进程同步

    千次阅读 多人点赞 2019-02-02 17:27:43
    操作系统4————进程同步 一.目录 操作系统4————进程同步 一.目录 二.进程同步的基本概念 1. 同步机制的引入目的 2. 临界资源 3. 临界区 4. 两种形式的制约关系 5. 同步机制应遵循的...

    操作系统4————进程同步

    一.目录

    二.进程同步的基本概念

    1. 同步机制的引入目的

    在多道程序环境下,进程是并发执行的,不同进程之间存在着不同的相互制约关系。为了协调进程之间的相互制约关系,引入了进程同步的概念。

    2. 临界资源

    虽然多个进程可以共享系统中的各种资源,但其中许多资源一次只能为一个进程所使用,我们把一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如打印机等。此外,如果变量、数据等都可以被若干进程共享,也属于临界资源。

    3. 临界区

    对临界资源的访问,必须互斥地进行,在每个进程中,访问临界资源的那段代码称为临界区。

    我们可以进入访问临界资源的代码分为4个区:

    • 进入区。为了进入临界区使用临界资源,在进入区要检查可否进入临界区,如果可以进入临界区,则应设置正在访问临界区的标志,以阻止其他进程同时进入临界区。
    • 临界区。进程中访问临界资源的那段代码,又称临界段。
    • 退出区。将正在访问临界区的标志清除。
    • 剩余区。代码中的其余部分。即:
        do {  
        entry section; //进入区  
        critical section; //临界区  
        exit section; //退出区  
        remainder section; //剩余区  
        } while (true)  
    

    4. 两种形式的制约关系

    b.直接相互制约关系(同步):直接相互制约关系是指,为了完成某个目而建立的两个或多个进程,这些进程需要在某些位置协调工作次序,信息传递而产生的制约关系,直接相互制约关系是由于进程间的相互合作而引起的。

    比如说AB进程,A产生数据,B计算结果,AB公用一个缓存区。缓存区为空时,B不能运行,等待A向缓存区传递数据后B才能运行,缓存区满时,A不能运行,等待B取走数据后,A才能运行。此时AB为直接制约关系。

    a.间接相互制约关系(异步):间接相互制约关系是指当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区后,另一进程才允许去访问此临界资源。

    比如AB进程都需要使用打印机,如果进程A需要打印时, 系统已将打印机分配给进程B,则进程A必须阻塞。一旦进程B将打印机释放,系统便将进程A唤醒,并将其由阻塞状态变为就绪状态

    5. 同步机制应遵循的规则

    • 空闲让进:当无进程处于临界区时,表明临界资源处于空闲状态,应允许一个请求进入临界区的进程立即进入自己的临界区,以有效利用临界资源。
    • 忙则等待:当已有进程进入临界区时,表明临界资源正在被访问,因而其他试图进入临界区的进程都必须等待,以保证对临界资源的互斥访问。
    • 有限等待:对要求访问的临界资源的进程,应保证在有限时间内能进入自己的临界区,以免陷入“死等”状态。
    • 让权等待:当进程不能进入自己的临界区时,应立即释放处理机,以免陷入"忙等"状态

    三.软件同步机制

    在进入区设置和检查一些标志来标明是否有进程在临界区,如果已有进程在临界区,则在进入区通过循环检查进行等待,进程离开临界区后则在退出区修改标志。

    1. 算法一:单标志法。

    思想: 该算法设置一个公用整型变量turn,用于指示被允许进入临界区的进程编号,比如turn = 0 ,则允许P0进程进入临界区。该算法可确保每次只允许一个进程进入临界区。

    伪代码:

    // P0进程
    while(turn!=0);  // 进入区
    critical section; //临界区
    turn=1; //退出区
    remainder section; //剩余区
    
    // P1进程
    while(turn!=1);  // 进入区
    critical section; //临界区
    turn=0; //退出区
    remainder section; //剩余区
    

    评价: 两个进程必须交替进入临界区,如果某个进程不再进入临界区了,那么另一个进程不再进入临界区(违背“空闲让进”)这样很容易造成资源利用的不充分。

    2. 算法二:双标志法先检查

    思想:该算法的基本思想是在每一个进程访问临界区资源之前,先查看一下临界资源是否正在被访问,若被访问,该进程需等待;否则,进程才进入自己的临界区。为此,设置了一个数据flag[i],如果第i个进程值为FLASE,则表示Pi进程未进临界区,值为TRUE,表示Pi进程进入临界区。

    伪代码

    //pi进程
    while(flag[j]); //进入区  ① 
    flag[i] = TRUE;//进入区 ③
    critical section;//临界区
    flag[i] = FALSE;//退出区
    remainder section;//剩余区
    
    //pj进程
    white(flag[i]);//进入区 ②
    flag[j] = TRUE //进入区  ④ 
    critical section;//临界区
    flag[j] = FLASE; //退出区
    remainder section;//剩余区
    

    评价: 优点:不要交替进入,可连续使用;缺点:pi和pj可能同时进入临界区,按序号①②③④执行,会同时进入临界区(违背”忙则等待“)。即在检查对方flag之后和切换自己的flag之间有一段时间,结果都检查通过。这里问题出在检查和修改操作不能一次进行。

    3. 算法三:双标志法后检查

    思想: 算法二先检测进程状态标志后,再置自己标志,由于在检测和放置中可插入另一个进程到达时的检测操作,会造成两个进程分别检测后。同时进入临界区。为此,算法三采用先设置自己标志为TRUE,再检测对方状态标志,若对方标志为TURE,则进程等待,否则进入临界区

    伪代码:

    // Pi进程  
    flag[i] =TRUE;  
    while(flag[j]);  
    critical section;  
    flag[i] =FLASE;  
    remainder section;
    
    // Pj进程  
    flag[j] =TRUE;  // 进入区  
    while(flag[i]);  // 进入区  
    critical section;  // 临界区  
    flag [j] =FLASE;   // 退出区  
    remainder section;  // 剩余区 
    

    评价: 当两个进程几乎同时想要进入临界区时,他们分别将自己的标志值flag设置为TRUE,并且同时检测对方的状态(执行while语句),发现对方也要进入临界区,预算对方互相谦让了,结果谁也进不了临界区,从而导致"饥饿"现象。

    4. 算法四:Peterson’s Algorithm

    思路: 为了防止两个进程为进入临界区而无限等待,又设置变量turn,指示不允许进入临界区的进程编号,每个进程在设置自己的标志后再设置turn标志,不允许另一个进程进入。这时,在同时检测另一个进程状态标志和不允许进入标志,这样可以保证两个进程同时要求进入临界区,只允许一个进程进入临界区

    代码:

    // Pi进程  
    flag[i]=TURE; turn=j;  
    while(flag[j]&&turn==j);   
    critical section;  
    flag[i]=FLASE;  
    remainder section; 
    
    // Pj进程  
    flag[j] =TRUE;turn=i;  // 进入区  
    while(flag[i]&&turn==i);   // 进入区  
    critical section;  // 临界区  
    flag[j]=FLASE;  // 退出区  
    remainder section;  // 剩余区  
    

    评价: 本算法的基本思想是算法一和算法三的结合。利用flag解决临界资源的互斥访问,而利用turn解决“饥饿”现象。

    四.硬件同步机制

    虽然可以利用软件方法解决诸进程互斥进入临界区的问题,但有一定难度,并且存在很大的局限性,因而现在已很少采用,相应的许多计算机已提供了一些特殊的硬件指令,允许对一个字中的内容进行检查和修改,或者是对两个字的内容进行交换等。

    实际上,对临界区进行管理时,可以将标志看做一个锁,“锁开”进入,"锁关"等待,初始时,锁打开。每次进程要进入临界区时,检测锁。打开时,进入;关闭是,等待。

    1. 关中断

    思想: 在进入锁测试之前关闭中断,直到完成锁测试并上锁之后才能打开中断。这样,进程在临界区执行期间,计算机系统不响应中断,从而不会引发调度,也就不会打发生进程或者线程切换

    缺点:

    1. 滥用关中断权利可能会导致严重的后果
    2. 关中断时间过长,会影响系统效率,限制了处理器交叉执行程序的能力;
    3. 关中断方法也并不适用于多CPU系统,因为在一个处理机上关中断并不能防止其他进程在其他处理器上执行相同的临界段代码。

    2. 利用Test-and-Set指令实现互斥

    思想: 借助一条硬件指令——"测试并建立"指令TS以实现互斥的方法,TC指令是原子操作,即执行过程不可分割

    TS指令描述如下:

    boolean TS (boolean *lock){
        boolean old;
        old = *lock;
        *lock = TRUE;
        return old;
    }
    

    用TS指令管理临界区时,为每个临界资源设置一个布尔变量lock,lock初值为FALSE,表示该临界资源空闲。进程在进入临界区之前,首先用TS指令测试lock,如果其值为FALSE,则表示没有进程在临界区内,可以进入,并将TRUE值赋予lock,这等效于关闭临界资源.如果其值为TRUE,则重复检查,直到进程退出。

    伪代码

    do{
        ···
        while TS(&lock);
        critical seetion;
        lock = FALSE;
        remainder sectionl
        
    }while(TRUE);
    

    3. 利用Swap指令实现互斥

    Swap指令称对换指令,在Intel 80*86中又称XCHG指令,用于交换两个字的内容。

    Swap指令描述如下

     void swap (boolean *a,boolean *b){
         boolean temp;
         tamp = *a;
         *a = *b
         *b = temp;
     }
    

    用Swap指令可以简单有效的实现互斥,方法是为每一个临界资源设置一个全局的boolean变量lock,其初值为false,在每个进程中再利用一个局部变量key。

    伪代码

    do{
        key = TRUE;
        do{
            Swap(&lock,&key);
        }while(key!=FALSE);
        
        临界区操作
        lock= FALSE;
    }
    

    五.信号量机制

    信号量机制是一种功能性比较强的机制,可以用来解决互斥与同步的问题,它只能被两个标准的原语wait(S)和Signal(S)来访问,也可以记做“P操作”(通过)和“V操作”(释放)。wait和signal都属于原子操作。

    1. 整形信号量

    整形信号量就是用整形量S表示资源数目的多少。

    P操作

    wait(S){
        while(S<=0);
        S--;
    }
    
    

    v操作

    signal(S){
        S++;
    }
    

    wait操作中,只要信号量S<=0,就会不断地测试。因此,该机制并未遵循“让权等待” 的准则,而是使进程处于“忙等”的状态。

    2. 记录型信号量

    记录型信号量是不存在“忙等”现象的进程同步机制。除了需要一个用于代表资源数目的整型变量value外,再增加一个进程链表L,用于链接所有等待该资源的进程,记录型信号量是由于釆用了记录型的数据结构得名。记录型信号量可描述为:

    typedef struct{  
        int value; //资源数量  
        struct process *L;  //进程链表
    } semaphore;
    

    P操作

    void wait (semaphore S) { //相当于申请资源  
        S.value--;  
        if(S.value<0) {  
            add this process to S.L;  
            block(S.L);  //,表示该类资源已分配完毕,因此进程应调用block原语,进行自我阻塞
        }  
    } 
    
    

    v操作

    oid signal (semaphore S) {  //相当于释放资源
        S.value++;
        if(S.value<=0){
            remove a process P from S.L;
            wakeup(P);//将第一个等待进程唤醒。
        }
    }
    

    3. AND信号量

    上述进程互斥问题都是针对一个临界资源而言的,在有些应用场合,一个进程需要同时获得两个或者更多的资源。AND信号量可以解决多临界资源申请问题。假设有S1,…Sn,N个资源,进程必须申请到所有资源后才可执行,则其wait 和signal描述为:
    P操作

     void wait(S1, S2, ... , Sn){
    	if (S1>=1 && S2>=1 && ... && Sn>=1 ) {
    		 for (int i=1; i<n; i++) 
    			 Si = Si - 1; 
    	}
    	else place this process//将当前进程放置在第一个不满足Si>=1的阻塞队列中 
    }
    

    v操作

    void signal(S1, S2, ... , Sn){ 
    	for (int i=1; i<n; i++) 
    		Si = Si + 1;
    	 romove all the process waiting in the queue associated with Si into ready queue 
    }
    

    4. 信号量集

    在记录型信号量机制中,wait和signal操作只能进行加一减一的操作。当需要一次性需要申请N个同类资源时,需要进行N次操作,这显然是低效的。为方便对资源的控制,每种资源在分配前需要检查其数量是否在其极限值之上。为此,对AND信号量进行扩充。S为信号量,d为需求量,t为下限值:
    P操作

    void wait(S1, d1, t1, S2, d2, t2, ... , Sn, dn, tn){ 
    	if (S1>=t1 && S2>=t2 && ... && Sn>=tn ) 
    		for (int i=1; i<n; i++) 
    			Si = Si - dn; 
    	else place this process//将当前进程放置在第一个不满足Si>=1的阻塞队列中 
    }
    

    v操作

    void signal(S1, d1, S2, d2, ... , Sn, dn,){ 
    	for (int i=1; i<n; i++) 
    		Si = Si + dn;
           romove all the process waiting in the queue associated with Si into ready queue 
    }
    

    六.管程机制

    1.引入管程的目的

    虽然信号量机制是一种既方便又有效的同步方式,但每个要访问临界资源的进程都必须同时自备同步操作wait(S)和signal(S),这就使大量的同步操作分散在各个进程中。这样不仅给系统的管理者带来麻烦,而且还会因同步操作的使用不当而导致系统死锁。这样,在解决上述问题的过程中,便产生了新的进程同步工具———管程

    2.管程的定义

    系统中的各种硬件资源和软件资源,均可用数据结构抽象地描述其资源特性,即用少量信息和对资源所执行的操作来表征该资源,而忽略了它们的内部结构和实现细节。管程是由一组数据以及定义在这组数据之上的对这组数据的操作组成的软件模块,这组操作能初始化并改变管程中的数据和同步进程。

    3.管程的特性

    1. 局部于管程的数据只能被局部于管程内的过程所访问。
    2. 一个进程只有通过调用管程内的过程才能进入管程访问共享数据。
    3. 每次仅允许一个进程在管程内执行某个内部过程。由于管程是一个语言成分,所以管程的互斥访问完全由编译程序在编译时自动添加,无需程序员关注,而且保证正确。

    4.管程的组成

    1. 局部于管程的共享结构数据说明。
    2. 对该数据结构进行操作的一组过程。
    3. 对局部于管程的共享数据设置初始值的语句。

    七.参考资料

    进程同步(操作系统)
    《操作系统 第四版》

    展开全文
  • 进程同步橘子苹果问题
  • 用三个算法实现读者写者问题,包括写优先、无优先、读优先等,下载即可使用。
  • 进程同步

    2019-04-13 18:33:11
    为什么要引入进程同步? 在多道程序环境下,程序是并发执行的,不同进程之间存在着不同的相互制约关系,为了协调进程之间的相互制约关系,引入了进程同步的概念。在操作系统中,要对并发进程进行同步的原因是并发...

    基本概念

    为什么要引入进程同步?

    在多道程序环境下,程序是并发执行的,不同进程之间存在着不同的相互制约关系,为了协调进程之间的相互制约关系,引入了进程同步的概念。在操作系统中,要对并发进程进行同步的原因是并发进程是异步的。

    临界资源

    一次仅允许一个进程使用的资源称为临界资源,如打印机、公用队列等。对临界资源的访问必须互斥地进行。在每个进程中,访问临界资源的那段代码称为临界区。
    临界资源的访问分为4个部分:
    ①进入区:检查可否进入临界区,若可以进入,则设置标志。
    ②临界区:进程中访问临界资源的那段代码,又称临界段。
    ③退出区:清除标志。
    ④剩余区:代码中的其他部分。

    同步

    同步又称直接制约关系。是指为了完成某个任务而建立的两个或多个进程,这些进程需要协调工作次序,它们的制约关系源自它们之间的相互合作。
    例:读进程和写进程对同一段缓冲区的读和写。

    互斥

    互斥又称间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待。
    例:访问打印机。
    同步机制应该遵循以下准则:
    ①空闲让进。临界区空闲可以允许进程进入。
    ②忙则等待。已有进程进入临界区则其他进程必须等待。
    ③有限等待。对请求访问的进程,保证在有限时间内进入临界区。
    ④让权等待。当进程不能进入临界区应立即释放处理器。

    展开全文
  • 进程同步编程实例

    2012-02-24 09:39:03
    C语言编写的进程同步编程实例。可以参考使用semget semctl semop等函数。
  • 选择一个进程同步的经典问题,包括生产者消费者问题,写者问题,哲学家就餐问题和理发师睡眠问题,写一个程序来模拟。
  • 进程同步和通信 进程同步 在OS中引入进程后,一方面使系统的吞吐量和资源的利用率得到提升,另一方面也使得系统变得复杂,如果没有合理的方式对进程进行妥善的管理,必然会引起进程对系统资源的无序竞争,使系统...

    进程同步和通信

    进程同步

    在OS中引入进程后,一方面使系统的吞吐量和资源的利用率得到提升,另一方面也使得系统变得复杂,如果没有合理的方式对进程进行妥善的管理,必然会引起进程对系统资源的无序竞争,使系统变得混乱;为了实现对并发进程的有效管理,在多道程序系统中引入了同步机制,常见的同步机制有:硬件同步机制、信号量机制、管程机制等,利用它们确保程序执行的可再现性;

    进程同步的基本概念

    两种形式的制约关系

    1. 间接相互制约:由于多个进程并发执行时,共享系统资源,致使这些进程在执行时形成相互制约的关系。为了使共享系统资源的进程有序执行,系统资源必须统一分配,即进程需要先申请后使用;
    2. 直接相互制约:多个进程为了完成同一项任务而合作,在合作过程中形成相互制约的关系;

    这里所说的制约关系,其实是一种相互影响的关系,即某一个进程的运行除了受到系统影响外还会受到其他进程运行情况的影响;而上面两种分类方式的依据是产生影响的原因;

    临界资源

    在操作系统引论中介绍操作系统的四大特性之一“共享”时曾提到,对于资源的共享有两种方式:互斥共享和同时访问。其中需要互斥访问的资源就是临界资源;所谓互斥访问,就是指在进程A对资源X的处理结束前,其他进程不允许对X进行处理;这里的临界资源既包括硬件资源也包括软件资源;

    临界区

    对于临界资源进行访问的代码,即为临界区;在进入临界区之前,需要检查是否可以访问互斥资源,这一部分代码即为进入区;在退出临界区时,需要释放对临界资源的占有,这一部分代码即为退出区;然后我们把剩下的其余代码成为剩余区

    同步机制应遵守的规则

    1. 空则让进:临界资源如果处于空闲状态,那么该进程可以进入其临界区;
    2. 忙则等待:临界资源如果处于被占用状态,那么该进程需要等待临界资源被释放;
    3. 有限等待:进程在有限时间内可以进入自己的临界区,以避免陷入“死等”状态;
    4. 让权等待:当进程不能进入自己的临界区时,需要让出处理机,以避免陷入“忙等”状态;

    进程同步的方式

    硬件同步机制

    利用软件方法可以解决进程互斥进入临界区的问题,但是有一定的难度和局限性,现已很少使用。通常计算机会提供一些特殊的硬件指令,允许对一个字中的内容进行检测和修正,或者对两个字的内容进行交换;对临界区的管理,可以视为对“锁”的管理:当“锁”开的时候,就允许进入,然后把“锁”关上;当“锁”关上的时候,就只能在外面等待;显然,对“锁”的检测(相当于进入区代码)和打开“锁”(相当于临界区)的操作必须是连续的;常见的硬件同步机制有:

    1. 关中断

      是实现互斥的最简单方法之一。在进入锁检测之前,关闭中断,知道完成锁检测并上锁之后才打开中断。这样,进程在临界区执行期间,计算机系统不响应中断,从而不会引发调度,自然不会发生进程或者线程切换。但是关中断的方法有许多缺点:1。滥用关中断权利,可能会造成严重后果;2. 关中断时间过长,会影响系统效率,限制处理器交叉执行程序的能力;3.关中断的方法不适合多CPU系统;

    2. 利用Test-and-Set 指令实现互斥

      TS指令的一般描述如下:

      boolean TS(boolean *lock){
          boolean old;
          old=*lock;
          *lock=true;
          return old;
      }
      相应的进入区代码为:
      while(TS(&lock));
      

      TS指令中,当lock为false时,就将其设置为true,然后返回false;当lock为true时,就返回true;

      返回false表示资源可用;返回true表示资源不可用;

      上面这段代码实现的功能:如果lock为false,那么设置它为true,但是要返回false;如果lock为true,不做改变,那么仍旧返回true;但实际上,它是这么做的:不论lock是什么,都把它设置为true。而返回它原来的值;

    3. 利用Swap指令实现互斥

      void Swap(boolean* lock,boolean* key){
          	boolean temp=*lock;
          	*lock=*key;
          	*key=temp;
      }
      相应的进入区代码为:
      key=true;
      do{
          Swap(&lock,&key);
      }while(key!=false);
      //进入临界区
      

      Swap指令中,do-while循环中的退出条件是key为false ;而key为false 意味着lock为false,表示资源可用;当lock为true的时候,key就为true;那么循环就会一直进行下去;感觉还是蛮绕的,分类看看:

      进入Swap之前进入Swap之后是否再次进入Swap
      lockfalse,keytrue(资源可用)locktrue,keyfalse(允许进入临界区)
      locktrue,keytrue(资源不可用)locktrue,keytrue(不允许进入临界区)

      这里,我们可以看出,当资源不可用是,进入Swap并没有任何改变,这是符合功能的:资源不可用,当然检查多少遍都不可用嘛;

      由于资源是共享的,所以这里的lock作为资源的标记之一,必然会被多个进程访问,所以,当一个拥有资源的进程使用完该资源的时候,需要将lock设置为false,以便让其他进程使用,这就是退出区代码的任务啦;

      利用TS机制和Swap机制,都会让进程处于忙等状态,并不符合同步机制的要求;(准确的说,不是实现不了同步,而是效率不高,不太高效~)

    信号量同步机制

    信号量同步机制由Dijkstra(很厉害的大神,单源最短路劲算法就是他提出的);信号量机制已被广泛应用到单处理机和多处理机系统以及计算机网络中;

    1. 整型信号量

      整型信号量S表示资源数目,除初始化外,仅能通过两个标准的原子操作进行修改:wait(S)和signal(S);这两个操作长期以来也别称为P、V操作;

      wait(S){
          while(S<=0);
          S--;
      }
      signal(S){
          S++;
      }
      

      其实问题就是,wait和signal两个原子操作仍旧会产生“忙等”——进程不断测试,一直问,你说烦不烦?

    2. 记录型信号量

      记录型信号量机制是一种不存在忙等现象的进程同步机制;但是采取了让权等待策略后,就会有多个进程等待访问统一资源的情况,于是还需要把这些进城组织起来,于是除了S用来表示资源的数量外,还需要一个指针;这也是记录型信号量的名称来源:使用了记录型的数据结构;

      typedef struct{
          int value;
          sturct process_control_block *list;
      }semaphore;
      wait(semaphore *S){
          S->value--;
          if(S->value<0){
              block(S->list);
          }
      }
      signal(semaphore *S){
          S->value++;
          if(S->value<=0){
              wakeup(S->list);
          }
      }
      

      记录型信号量中,value不仅指示资源的数量,由于每次wait操作value都会递减,所以value的值会反映出等待资源的进程有多少个。在signal中,value经过自增后,如果还<=0,说明还有进程在等待该资源,所以需要wakeup一个进程;

    3. AND型信号量

      前面所述的进程互斥问题针对的是多个并发进程共享一个临界资源的情况,但是如果多个进程共享多个资源时仍旧采取这样单个的分配方法,就有可能发生死锁现象;为了避免这样的现象,提出来AND型信号量:将进程在整个运行过程中需要的所有资源,要么一次性全部分配给进程,然后使用完后再一起释放。要么一个都不分配,这样便可以避免死锁现象。wait和signal操作要做出相应改变。

      Swait(S1,S2,S3,S4,S5....){
      	while(true){
              if(S1>=1&&S2>=1...){
             		for(i=1;i<=n;i++){
                  	Si--;
              	}
              	break;
          	}else{
                  //找到第一个小于等于0的Si,然后将进程放置到与其相关的等待队列中
          	}
      	}
      }
      Ssignal(S1,S2...Sn){
          while(true){
              for(i=0;i<=n;i++){
                  Si++;
                  //唤醒一个等待Si资源的进程——该进程将进入Swait中的while循环里继续判断其他资源是否可用。
              }
          }
      }
      
      
    4. 信号量集

      前面介绍的几种信号量同步机制都是对某一资源进行一个单位的申请和释放。当一次需要N个的时候,就需要进行N次请求,这不但低效而且容易发生死锁情况;还有些情况下,为了保证系统的安全性,当所申请的资源低于某个值时,就需要停止对该类资源的分配。解决办法就是当进程申请某类临界资源时,都必须测试资源的数量,判断是否大于可分配的下限值,然后决定是否分配;

      基于上述提到的两点问题,需要对AND信号量机制加以扩充,对进程所申请的所有资源以及每类资源不同的资源需求量,再一次PV原语操作中完成申请和释放。对信号量Si的测试值不再是1,而是ti。当Si<=ti时就不再分配;同时,进程需要传递给wait方法每类资源所需要的数目,由此形成一般化的“信号量集”机制;

      Swait(S1,t1,d1....Sn,tn,dn);表示对Si类资源的需求是di个,当Si的数量小于ti时就不再分配;
      Ssignal(S1,d1....Sn,dn);表示归还Si类资源的数目是di个;
      

      特殊的,Swait(S,d,d)表示信号量集中只有一个信号量;它允许每次申请d个资源,当资源数量小于d时不予分配;

      Swait(S,1,1)表示普通的一般记录型信号量;

    信号量的应用:

    1. 实现进程互斥:基本操作;
    2. 实现前驱关系:当进程A中的X1操作结束后才进行进程B中的X2操作,像这种需求即为前驱关系。可以设置一种虚拟的资源S,并设置其状态为不可用,然后在X1的后面加上signal(S),在X2语句前加上wait(S),以此实现这种执行顺序上的控制;

    管程机制

    信号量机制虽然是一种既方便又实用的进程同步机制,但是要访问临界资源的进程需要自备同步操作wait(S)和signal(S),这就使得对共享资源进行访问的代码遍布各个进程,不利于系统管理,还增加系统死锁的风险;管程机制是一种解决该问题的方法;

    操作系统的作用之一就是实现对计算机系统资源的抽象,管程机制使用少量的信息和对该资源所执行的操作来表征该资源,所以共享系统资源就变为了共享数据结构,并将对这些共享数据结构的操作定义为一组过程。进程对共享资源的申请、释放和其他操作必须通过这组过程。代表共享资源的数据结构以及由对该共享数据结构实施操作的一组过程所组成的资源管理程序共同构成了一个操作系统的资源管理模块,我们称之为管程;

    管程由四部分组成:名称、局部于管程的共享数据结构说明、对该数据结构进行操作的一组过程、对局部于管程的共享数据结构设置初始值的语句;

    所有进程访问临界资源时,都只能通过管程间接访问,而管程每次只准许一个进程进入管程,从而实现互斥。管程体现了面向对象程序设计的思想;具有:模块化,即管程是一个独立的基本单位,可单独编译;抽象数据类型,不仅有数据还有对数据的操作;信息隐蔽,管程中的数据结构只能被管程中的过程访问,这些过程也是在管程内部定义的,而管程之外的进程只需调用而无需了解其内部的具体实现细节。(这样,原来遍布系统的共享资源的访问代码,就集中到管程中啦);

    管程和进程的对比(两个截然不同的概念,有什么好对比的呢?大概是名字相似吧)

    1. 两者都定义了各自的数据结构,但是管程定义的数据结构是对公用资源的抽象,进程定义的是私有数据结构PCB;
    2. 两者都有对各自数据结构的操作,但是管程的操作是为了实现同步和初始化,进程是由顺序程序执行有关操作;
    3. 进程的目的是在于实现系统的并发,而管程的目的是解决共享资源的互斥访问;
    4. 进程是主动工作的,管程需要被其他程序使用,属于被动工作的;
    5. 进程有动态性,管程是操作系统中的一个资源管理模块;

    管程中还有一个比较重要的概念就是条件变量。当一个进程进入了管程但在管程中被阻塞或者挂起,此时该进程需要释放对管程的占有,并且根据阻塞或者挂起的原因,也就是条件变量,进入相应的等待队列,等待其他进程的唤醒。条件变量x具有两种操作:x.wait()和x.signal();

    x.wait():正在调用管程的进程因x条件而需要被挂起或者阻塞,则调用x.wait()将自己插入到条件变量x的等待队列上并释放管程,直到x条件变化;

    x.signal():正在调用管程的进程发现x条件发生了变化,重新启动一个因x而阻塞的进程,如果有多个进程因x而阻塞,也只能选择一个;

    如果进程Q因为x条件而处于阻塞状态,当P调用管程时,执行了x.signal()操作后,Q重新启动,此时P和Q到底谁来继续拥有管程呢?答案是两者均可;

    经典的进程同步问题

    这里只列出问题,不做具体介绍和分析,关于进程同步,其实更多的是线程同步,有一本很棒的书《图解Java多线程设计模式》,这本书讲解了12种如何利用多线程来编程的方法,每一种方法作者将其称为一种模式,其中就有下面提到的问题的解决方案。这十二种方法讲解了到底该如何安全地使用多线程(即考虑到线程的同步问题)

    1. 生产者-消费者问题;
    2. 哲学家进餐问题;
    3. 读-写问题;

    进程通信

    在进程之间要传送大量数据时,应当利用OS提供的高级通讯工具,该工具的特点是:

    1. 使用方便:OS隐藏了实现进程通信的细节,向用户提供一组用于实现高级通信的命令(原语),即通信过程是对用户是透明的;
    2. 高效传输大量数据:用户可以直接利用高级通信命令传输大量的数据;

    进程通信的类别

    高级通信机制分为四类:共享存储器、管道通信系统、消息传递系统以及客户机-服务器系统;

    共享存储器系统

    相互通信的进程通过共享某些数据结构或者共享存储区,进城之间通过这些空间实现通信;常见的有基于共享数据结构的通信方式和基于共享存储区的通信方式;

    1. 基于共享数据结构的通信方式

      通信进程共用某些数据结构来实行进程之间的信息交换。操作系统仅提供共享存储器,由程序员负责对公用数据结构的设置以及进程间同步的处理;这种方式仅适用于传输数据量少的情况下,通信效率低,属于低级通信;

    2. 基于共享存储区的通信方式

      为了传输大量数据,在内存中划出一块共享存储区域,各个进程通过对该共享区的读或者写交换信息,从而实现通信;数据的形式和位置甚至访问方式都是由进程负责。这种通信方式属于高级通信;需要通信的进程首先向系统申请获得共享存储区的一个分区,将其添加到自己的地址空间,当通信结束后,再将此区域归还系统;

    管道通信系统

    管道,是指用于连接一个读进程和一个写进程以实现他们之间通讯的一个共享文件,有名pipe文件;写进程将信息以字符流的形式送入管道;而读进程将从管道中接受数据。由于通信双方通过管道文件通信,所以这种通信方式也称为管道通信;管道通信需要解决三个问题:

    1. 互斥:对管道文件的访问需要互斥进行,写进程和读进程不能同时对pipe文件操作;
    2. 同步:写进程不能无限对pipe文件写入,通常,当写入一定量的信息后,写进程就会睡眠,直到读进程读取了信息后再唤醒写进程;
    3. 确定对方是否存在:只有确定对方已存在时才能进行通信,否则,只有写进程的话,就没有进程把它唤醒;而只有读进程的话,由于没有内容,所以它可能一直等待而无法执行其他代码;

    消息传递系统

    在该机制中,进程不必借助任何共享存储区或者数据结构即可实现通信,它以格式化的消息为单位,将信息封装在消息中,利用操作系统提供的消息发送原语,在进程之间实现消息传递,完成数据交换;

    该通信方式隐藏了通信细节,使通信过程对用户透明化,降低了通信程序设计的复杂性和错误率,成为当前应用最为广泛的一种进程同信机制;由于该机制能很好支持多处理机系统、分布式系统和计算机网络,因此也成为这些领域中最主要的通信工具;

    基于消息传递系统的进程间通信属于高级通信方式,按照其实现方式的不同,进一步分为:直接通信方式和间接通信方式;其中直接通信方式使用操作系统提供的原语操作,直接将信息发送到接受进程;间接通信方式通过共享中间实体(被称为邮箱)来实现进程间通信;

    在直接通信方式中,存在两种寻址方式,一种是对称寻址方式,另一种是非对称寻址方式;

    对称寻址方式中,接收方需要明确指出发送方的标记,发送方需要明确指出接收方的标记,问题就是一旦某个进程改变了该标记,所有与其有通信的进程都需要做出改变,不利于实现进程定义的模块化;

    非对称寻址方式中,接收方不需要明确指出发送方的标记,只需填写表示原进程的标记,但是发送方需要指出接收方的标记;

    发送进程和接受进程之间要能通行,就需要建立通信链路。有两种方式建立通信链路,一种是发送进程在通信前显式调用“建立连接”命令请求系统为之建立一条通信链路;链路在使用完毕后拆除,这种方式主要用于计算机网络中;另一种是,发送进程无需显式提出建立链路的请求,由系统自动为之建立一条链路;这种方式主要用于单机系统中;

    而根据通行方式的不同,链路又可以分为:单向链路和双向链路;单向链路只允许发送进程向接收进程发送消息,不允许接收进程向发送进程发送消息;双向进程则可以实现双向通信;

    关于信箱通信:

    信箱被定义为一种数据结构,每个信箱都有一个唯一的标识符,消息在邮箱种可以安全地存取,只有被核准的目标用户才能随时读取;

    信箱的结构逻辑上包含:

    1. 信箱头,由于存放关于信箱的描述信息,如信箱ID,信箱的拥有者,信箱口令,信箱的空格数等;
    2. 信箱体,由若干个可以存放消息的信箱格组成;

    信箱的类型包括:

    1. 私用邮箱:由用户进程创建,只有邮箱的拥有者才能从邮箱里读取消息,其他进程只能向该邮箱发送消息;当拥有该邮箱的进程消失时,邮箱也就消失了;
    2. 公用邮箱:由操作系统创建,供给系统中的所有核准进程使用,核准进程既可以把消息发送到该邮箱也可以从该邮箱里读取信息。通常,公用邮箱在系统运行期间一直存在;
    3. 共享邮箱:由某进程创建,所有共享该邮箱的进程都可以取走该邮箱中自己的邮件;其实算得上是小范围里的公用邮箱吧;

    客户机-服务器系统

    前面三种方式,共享存储区域、管道、消息传递系统也可以实现不同计算机进程之间的双向通信,但客户机-服务器系统的通信机制在网络环境中的各种应用领域已成为主流的通信实现方式;其主要有两类:套接字、远程过程调用或远程方法调用;

    1. 套接字

      套接字来源于Unix操作系统,被设计用于同一台主机上的多个应用程序之间的通信,主要是为了解决多对进程同时通信时端口和物理线路的多路复用问题。

      一个套接字就是一个通信标记类型的数据结构,包含通信的目的地址、通信使用的端口号、通信网络的传输层协议、进程所在的网络地址,以及针对客户或者服务器程序提供的不同系统调用等,是进程通信和网络通信的基本构件。套接字为客户机-服务器模式而设计,主要分为基于文件的和基于网络的两种;

      1. 基于文件:通信进程位于同一台主机,套接字基于本地文件系统支持,一个套接字关联一个特殊的文件,通信进程通过该文件实现通信,类似管道通信;
      2. 基于网络:通信进程位于不同主机的网络环境下,通常采用非对称方式通信。通信的发起者需要提供接受者的命名;发送进程提出连接请求时,随机申请一个套接字,主机将为之分配一个端口与该套接字绑定。接受进程通过监听端口等待客户的请求,一旦收到请求,就接受连接,实现进程之间的通信;当通信结束后系统通过关闭接受进程的套接字来撤销连接;

      套接字的优势在于,不但可以用于本地计算机内部的进程通信,还适用于网络环境中的不同计算机间的进程通信。每一个套接字都拥有一个唯一的套接字号,这样系统中所有的连接都持有唯一的一对套接字及其端口连接,可以方便地区分来自不同应用程序进程的连接通信,确保了通信双方之间逻辑链路的唯一性,便于实现数据传输的并发服务,还隐藏了通信设施及其实现细节;

    2. 远程过程调用或远程方法调用

      远程过程调用RPC是一个通信协议,适用于通过网络连接的系统。该协议允许运行于一台主机系统(本地)上的进程调用另一台主机(远程)上的进程,对程序员表现为一般过程调用。在面向对象程序设计当中,这也称之为远程方法调用;

      负责处理远程过程调用的进程有两个,一个是本地客户进程,另一个是远程服务器进程,这两个进程通常也称为网络守护进程,负责网络间的消息传递;

      为了实现RPC的透明性,使得调用者感受不到此次调用的过程发生在其他主机上,RPC引入存根的概念:在本地客户端,每个能够独立运行的远程过程都对应一个客户存根,本地进程调用远程过程的实际是调用该过程所关联的存根。与此类似,每个远程进程所在的服务器端,其所对应的实际可执行进程也关联一个服务器存根。本地客户端存根于对应的服务器存根一般也是出于阻塞状态,等待消息;

      客户端发起RPC的主要步骤是:

      1. 本地过程调用者A以一般形式调用远程过程B在本地关联的客户存根CStub,传递参数并将控制权交给CStub;
      2. CStub完成包括过程名、调用参数等信息的消息的简历,将控制权交给本地客户进程;
      3. 本地客户进程完成与服务器的消息传递,将消息发送到远程服务器进程;
      4. 远程服务器进程接收到消息后,根据其中的过程名找到服务器存根SStub,将消息转交给SStub;
      5. SStub接收到消息后,从阻塞状态转入执行,从消息中取出过程调用的参数,然后调用与之关联的服务器进程;
      6. 服务器进程运行完毕后将结果返回给服务器存根SStub;
      7. SStub将结果打包为消息,将控制权转交给远程服务器进程;
      8. 远程服务器进程将消息发回客户端;
      9. 本地客户进程接收到消息后,根据其中的过程名找到与之关联的客户端存根CStub,将控制权和消息交给CStub;
      10. CStub从消息中取出结果,然后将其返回给本地调用者A,完成控制权的转移;
      11. 结束
    展开全文
  • 加深对并发协作进程同步与互斥概念的理解,观察和体验并发进程同步与互斥操作的效果,分析与研究经典进程同步与互斥问题的实际解决方案。了解Linux系统中IPC进程同步工具的用法,练习并发协作进程的同步与互斥操作的...
  • 操作系统实验报告 北邮大三上 进程同步实验报告
  • 进程同步C语言实验

    2011-12-29 20:58:54
    进程同步,操作系统,C语言程序实验
  • 操作系统——进程同步与互斥

    千次阅读 2019-10-21 22:13:19
    文章目录进程同步与互斥简介进程间合作进程间合作的问题竞争条件原子操作临界区相关的几个概念忙等待的互斥基于硬件的同步解决办法:屏蔽中断基于软件的同步解决方法严格轮换法Peterson解法N线程的软件方法基于软件...

    进程同步与互斥

    简介

    多线程并发会导致资源竞争。

    同步即协调多线程对共享数据的访问,保证任何时刻都只能有一个线程执行临界区代码。

    互斥是解决进程同步的方式。

    进程间合作

    独立进程是指一个进程在运行过程中不会与其他进程进行交互的进程。

    但是,进程在运行的过程中不可避免的要进行进程间合作。

    进程合作的优势:

    • 共享资源
      • 一台电脑,多个用户
      • 一个银行存储余额,多台ATM机
      • 嵌入式系统(机器人控制:手臂和手的协调)
    • 加速
      • I / O操作和计算可重叠
      • 多处理机——将程序分成多个部分执行
    • 模块快
      • 将大程序分解成小程序
        • 如编译系统。
      • 视系统易于扩展

    进程间合作的问题

    进程间合作要避免不确定性和不可重现性。由于进程调度的不确定性,因此进程的一个操作可能被打断。

    进程间通信要解决三个问题:

    1. 一个进程如何将信息传递给另一个进程
    2. 确保多个进程在关键活动中不会交叉,即进程互斥问题。
    3. 保证正确的访问顺序,即进程同步问题。

    竞争条件

    竞争条件是说多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序。

    案例:

    • 通过调用函数fork来创建一个进程。
      • new_pid = next_pid++;
      • 这一条语句翻译成汇编代码会是四句,因此要把他们当成一个原子操作去执行。
    • 两个程序并发执行访问并更改一个变量x。

    原子操作

    原子操作是指一次不存在任何中断或者失败的执行。

    • 该执行成功结束
    • 或者根本没有执行
    • 并且不应该出现任何部分执行的状态

    但是实际上操作往往不是原子的

    • 有些看上去是原子操作,但是实际上不是,如x++,实际上此条语句由三条汇编语言组成。
    • 有时甚至连单条机器指令都不是原子的,如Pipiline、super-scalar、out-of-order、page fault等。

    操作系统需要利用同步机制在进程并发执行的同时保证一些操作是原子操作。

    临界区相关的几个概念

    临界区是指多个程序访问临界资源的一段代码。也可以说是进程访问临界资源的一段需要互斥的代码。

    1. 在进入临界区前检查是否可进入临界区。
    2. 若可以进入,则设置相应标志表示正在访问临界区。
    3. 在访问完成之后将标志恢复为可访问临界区。
    4. 然后去执行非临界区代码。

    要避免竞争条件,即要找出某个途径来阻止多个进程同时读写共享数据,提出一种解决方案为互斥,即以某种手段保证当一个程序在使用一个共享爱那个文件或变量时,其他进程不能做同样的操作。

    互斥是指当一个进程处于临界区并访问共享资源时,没有其他进程会处于临界区并访问任何相同的共享资源。

    死锁是指多个进程相互等待完成特定任务二最终无法将自身任务进行下去。

    饥饿是指一个可执行的进程被调度器持续忽略,以至于虽然处于可执行状态却不被执行。

    避免竞争条件即使临界区中只能有一个进程。

    一个好的解决竞争条件的方案需要满足下列四个条件:

    1. 任何两个进程不能同时处于临界区
    2. 不应对CPU的速度和数量做任何假设
    3. 临界区外执行的进程不得阻塞其他进程
    4. 不得使进程无限期等待进入临界区
    5. 不能进入临界区的进程应该释放CPU资源(可选)。

    忙等待的互斥

    连续测试一个变量直到某个值出现为止称为忙等待,用于忙等待的锁称为自旋锁

    下列几种方式都可以保证任意两个进程不同时处于临界区。

    基于硬件的同步解决办法:屏蔽中断

    单处理器系统中,最简单的方法是使每个进程刚进入临界区后就立即屏蔽所有中断,并在就要离开之前再打开中断。屏蔽中断后,时钟中断也会被屏蔽,而CPU只有发生时钟中断或其他中断时才会进行进程切换,因此在屏蔽中断之后就不会被切换到其他进程。

    但是这种方式有一个问题:若此进程不打开中断的话其他进程就都无法执行。

    而且若是处于多处理器系统中,其他的CPU也可以将进程调度,从而还是无法避免多个进程同时访问临界区的问题。

    因此,屏蔽中断对用户进程不是一种合适的通用互斥机制。

    总结如下:

    • 硬件将中断处理延迟到中断被启用之后
    • 现代计算机体系结构都提供指令来实现禁用中断
      • 首先保存当前CPU状态
      • 然后禁用中断,访问临界区
      • 最后恢复CPU状态

    缺点:

    • 禁用中断之后,进程无法被停止。
      • 整个系统都会为之停下来
      • 可能导致其他进程处于饥饿状态
    • 临界区可能很长
      • 无法确定响应中断所需的时间

    基于软件的同步解决方法

    通过共享一些共有变量来同步进程的行为。

    严格轮换法

    在这里插入图片描述

    turn用来表示哪一个进程进入临界区,假设只有两个进程,进程0执行a代码,进程1执行b代码,此时考虑两种情况:

    1. 一个进程连续两次进入临界区,第一次进入临界区时发现turn是0,因此进入,在执行完临界区代码之后将turn的值设置为1,那么他在下次进入临界区之前发现turn不是0,因此一直循环等待,但此时临界区中是没有进程在执行的。
    2. 进程0先被调度执行,此时turn的值为0,因此进程0进入临界区执行代码,在它执行完临界区代码退出后,将turn的值更改为1,此时进程1被调度进入CPU执行,发现此时turn的值为1,因此执行临界区的代码,当临界区代码执行完毕之后将要更改turn的值时,CPU调度进程0进入CPU执行,但是此时turn的值还是为1,因此进程0不能执行临界区代码,但是此时临界区却没有进程在执行,因为违反了上面的第三条规则:为处于临界区的进程不得阻塞其他进程。

    由此可见,此种方式也不合适。

    Peterson解法

    在这里插入图片描述

    此算法可以解决两个进程的同步问题。

    N线程的软件方法

    进程Pi要等待从turn到i-1的进程都退出临界区后访问临界区。

    进程Pi退出时将turn给下一个想要进入的进程Pj。

    基于软件解决办法的分析

    • 复杂
      • 需要两个进程之间共享数据项
    • 需要忙等待
      • 浪费CPU时间

    更高级的抽象方法

    简介

    硬件提供了一些同步原语

    • 中断禁用,原子操作指令等

    操作系统提供更高级的编程抽象来监护进程同步

    • 如:锁、信号量
    • 用硬件原语来创建。

    原子操作指令

    现代CPU体系结构都提供一些特殊的原子操作指令。

    测试和置位(Test-and-set)指令

    • 从内存单元中读取值
    • 测试该值是否为1,然后返回真与假
    • 内存单元值设置为1

    交换(exchange)指令

    • 交换内存中的两个值。

    锁变量

    锁是一个抽象的数据结构

    • 一个二进制变量(锁定/解锁)
    • Lock::Acquire()
    • Lock::Release()

    使用锁来控制临界区的访问:当进程进入临界区之前先判断锁变量的值,若有锁的话就等待,否则进入临界区并且更改锁变量的值,然后再退出临界区时将锁变量的值再次修改。

    但是这又回到了最开始的问题:读锁变量和修改锁变量时两个操作,在第一个进程读取锁变量时发现可以进入,然后CPU调度第二个进程进入CPU进行执行,此时第一个进程还未将锁变量进行修改,因此第二个进程也发现可以进入,因此更改了锁变量进入临界区,此时又被切换至第一个进程,第一个进程认为此时临界区中没有进程,因此也进入了临界区,所以还是不能解决竞争条件的问题。

    使用TS指令实现自旋锁

    //忙等待,此种方式为自旋锁方式
    class Lock {
    	int value = 0;
    }
    Lock::Acquire() { //若锁被释放,则TS指令读取0并将值设置为1,否则,TS指令读取1并将值设置为1
    	while(test-and-set(value))
    		;
    }
    Lock::Release() {
    	value = 0;
    }
    
    //无忙等待,此种方式为等待队列方式,即阻塞式方法。
    class Lock {
        int value = 0;
        WaitQueue q;
    }
    Lock::Acquire() {
        while(test-and-set(value)) {
            //将当前进程加入等待队列
            add this PCB to wait queue q
            //执行调度
            schedule();
        }
    }
    Lock::Release() {
        value = 0;
        //从等待队列中移除一个进程p,并唤醒他去执行。
        remove one process p from q;
        wakeup(p);
    }
    

    基于原子操作指令锁的特征

    优点:

    • 适用于单处理器或者共享主存的多处理器任意数量的进程同步机制
    • 简单并且容易验证
    • 支持多临界区

    缺点:

    • 忙等待锁会消耗处理器时间
    • 可能导致饥饿
      • 进程离开临界区时有多个进程在等待
    • 死锁
      • 拥有临界区的低优先级进程
      • 请求访问临界区的高优先级进程获得处理器并等待临界区(忙等待的情况)

    参考资料

    清华大学—操作系统原理
    现代操作系统

    展开全文
  • 北邮操作系统第三次实验作业,进程同步。。C语言编写。。。windows环境下运行。。欢迎大家下载。。。↖(^ω^)↗。。附带实验报告哦。。亲

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 576,393
精华内容 230,557
关键字:

进程同步