一、进程同步与进程互斥

什么是进程同步

“进程同步”讨论的就是怎么解决“进程异步”的问题

什么是进程互斥



知识回顾与重要考点

二、进程互斥的软件实现方法

学习提示:

  1. 理解各个算法的思想、原理
  2. 结合上小节学习的“实现互斥的四个逻辑部分”,重点理解各算法在进入区、退出区都做了什么
  3. 分析各算法存在的缺陷(结合“实现互斥要遵循的四个原则”进行分析)

如果没有注意进程互斥?

单标志法


双标志先检查法

双标志后检查法

Peterson算法




让权等待:如果此时我这个进程进不了临界区,那么就应该立即释放出处理机资源,而不是继续在cpu上跑
但这个算法的处理方式是如果我这个进程此时进不了临界区,那么我会被一直卡在while循环这,然后其实自己还一直在cpu上执行,不断地来检查这个while循环条件是否满足。
所以虽然这个进程此时进不了临界区,但依然会占用cpu资源,因此没有满足 让权等待的原则

知识回顾与重要考点

三、进程互斥的硬件实现方法

学习提示:

  1. 理解各方法的原理
  2. 了解各方法的优缺点

中断屏蔽方法

不适用于多处理机:因为关中断指令只对执行关中断指令的那个处理机有用,所以如果此时处理机a执行关中断指令,那么就意味着在这个处理机上的进程不会被切换,那么这个进程就可以顺利地访问临界区,但是对于另一个处理机b来说还是会正常地切换进程,如果此时b上的进程也需要访问这个临界区,有可能会发生两个处理机上的两个进程同时对临界区进行访问的情况

只适用于。。:因为开关中断指令权限特别大,属于特权指令,在内核态下才能运行,因此,只适用于内核进程

TestAndSet指令

注意这里的代码只是为了表示逻辑,它在背后做了什么事情,实际上是硬件完成的,且不可以被中断

Swap指令

知识回顾与重要考点

四、信号量机制

复习回顾+思考:之前学习的这些进程互斥的解决方案分别存在哪些问题?
进程互斥的四种软件实现方式(单标志法、双标志先检查、双标志后检查、Peterson算法)
进程互斥的三种硬件实现方式(中断屏蔽方法、TS/TSL指令、Swap/XCHG指令)

  1. 在双标志先检查法中,进入区的“检查”、“上锁”操作无法一气呵成,从而导致了两
    个进程有可能同时进入临界区的问题;
  2. 所有的解决方案都无法实现“让权等待”
    1965年,荷兰学者Dijkstra提出了一种卓有成效的实现进程互斥、同步的方法——信号量机制

信号量机制

信号量机制——整型信号量


整型信号量有一个很大的缺陷,如果一个进程暂时进不了临界区,会一直占用处理机 ,一直循环检查,从而导致忙等的情况,不满足让权等待的原则

因此,又提出了记录型信号量

信号量机制——记录型信号量



知识回顾与重要考点

五、用信号量机制实现进程互斥、同步、前驱关系

之前学习了进程互斥的几种软件实现方式和硬件实现方式,但是它们都有一个共同的缺点,没有办法实现“让权等待”这个原则,而信号量机制当中,设置了进程的阻塞唤醒就刚好可以解决让权等待这个问题,所以信号量机制是一种更先进的解决方式

Tips:不要一头钻到代码里,要注意理解信号量背后的含义,一个信号量对应一种资源
信号量的值=这种资源的剩余数量(信号量的值如果小于0,说明此时有进程在等待这种资源)
P( S ) ——申请一个资源S,如果资源不够就阻塞等待
V( S ) ——释放一个资源S,如果有进程在等待该资源,则唤醒一个进程

信号量机制实现进程互斥

semaphore(信号量)
注意!!!这里虽然我们使用了“semaphore mutex = 1“这种简单的方式,但只要我们用semaphore这个关键字来开头的话,就意味着这个信号量并不是整形信号量,而是一个记录型的信号量,也就是说这个信号量是带有排队阻塞的功能的,并不会忙等

信号量机制实现进程同步

它们在系统中并发进行时,由于系统环境很复杂,所以操作系统在调度时,有可能p1先上处理机运行,有可能p2先上处理机运行,比如可能p2先4和5然后时间片用完了,又运行p1的1和2,接下来又切换回p2运行了6;总之并发运行所以它们之间的代码执行顺序是我们不可预知的,而有时我们又必须要让代码执行顺序按某种方式进行

如果代码4必须在代码2之后执行的话,则如上图

如果先P2:也就是说只有在P1执行了V操作之后,P2才有可能被唤醒上处理机运行,这就保证了代码2一定在代码4前运行

依然是用信号量表示某种资源来解决问题
刚开始S = 0表示刚开始这种资源是没有的,先执行P操作的话会被阻塞,这里只有P1才能唤醒P2进程,这就实现了进程之间的同步关系

信号量机制实现前驱关系

如果刚开始是P5这个进程上处理机运行,所要做的第一件事是对d这个信号量执行P操作,而由于d刚开始的值为0,所以它会被阻塞在这个地方,因此接下来就会发生进程调度换成另一个进程

知识回顾与重要考点

六、生产者消费者问题

问题描述

这是一个进程同步问题,”只有缓冲区没有满,生产者才能生产“,这是一个“一前一后”的同步关系;另外,第二对同步关系,“只有缓冲区不为空,消费者才能消费“;

最后一个条件是,缓冲区是临界资源,各进程必须互斥地访问缓冲区(假设此时有两个生产者进行在并发地运行,那么第一个生产者进程在检查缓冲区时,发生此时是空的,所以可以挑选其中的某一片往里面写入数据,与此同时,第二个生产者进程也并发地运行,它也发现此时缓冲区都是空的,因此它也会挑选其中的一块写入数据,假如它们挑的是同一片区域,后来的就会把前面的数据覆盖,所以缓冲区是一种临界资源,必须互斥地访问。所以这是一个互斥问题

问题分析


先看上面这对同步关系,消费者进程在消费之前需要消耗的是“产品”这个资源,所以它的这个P操作其实是在申请一个产品,申请一个数据,因此full这个同步信号量它所对应的资源应该是产品的数量,也就是非空缓冲区的数量,而从题目中给的条件我们可以知道缓冲区刚开始都是空的,也就是说刚开始产品这种资源的数量应该是0,因此full这个同步信号量的初始值是0

生产者进程每生产一个产品就需要消耗一个空闲的缓冲区,因此empty这个同步信号量,它所对应的资源就应该是空闲缓冲区这种资源,它的数量就应该是空闲缓冲区的数量,从题目给的条件我们知道,刚开始缓冲区都是空的,有n个缓冲区,因此empty这个同步信号量的初始值是n

如何实现

同步:执行V操作的这个进程会唤醒相对应的执行P操作的另一个进程

如果结合刚才给的同步关系的前驱图,就会发现这个代码其实完全可以根据前驱图的关系来得出

思考:能否改变相邻P、V操作的顺序?

刚才是先对同步信号量执行了P,再对互斥信号量执行P
现在我们尝试颠倒一下顺序,会发生什么情况呢?

知识回顾与重要考点

问题分析


七、多生产者-多消费者

问题描述

这里所谓的“多”不应该理解为“多个”,而是理解为“多类”,不同类别的生产者和不同类别的消费者他们所需要生产的和所需要消费的产品是不一样的(之前是只有一种产品)

问题分析

刚开始盘子中没有苹果,所以同步信号量apple初始值为0

刚开始盘子本来就是空的,所以父母在刚开始就可以向盘子中放入水果,所以同步信号量plate初始值为1

如何实现


刚开始,儿子、女儿进程即使上处理机运行也会被阻塞。如果刚开始是父亲进程先上处理机运行,则:父亲P(plate),可以访问盘子——>母亲P(plate),阻塞等待盘子——>父亲放入苹果V(apple),女儿进程被唤醒,其他进程即使运行也都会阻塞,暂时不可能访问临界资源(盘子)——>女儿P(apple),访问盘子,V(plate),等待盘子的母亲进程被唤醒——>母亲进程访问盘子(其他进程暂时都无法进入临界区)——>……


显然会出现父亲进程和母亲进程同时访问盘子这种临界区的情况,通过上个小节的讲解我们知道,如果两个生产者进程同时对一个缓冲区进行访问的话,有可能会导致数据覆盖的问题,这里也一样,因此如果我们在生产者消费者问题中,遇到缓冲区大小大于1的情况,就必须设置一个互斥信号量mutex来保证各进程互斥访问缓冲区;如果缓冲区大小等于1,有可能不需要,也不是绝对的

知识回顾与重要考点


八、吸烟者问题

问题描述

与之前介绍的生产者消费者不同的是,这个生产者可能会生产三种不同的产品,分别是三个消费者所需要的

问题分析

注意这里的缓冲区大小还是1,虽然“桌子上每次会放2种材料”,但是在这个题目中两种材料不能看成两种独立的物品,而是看成一种组合,所以应该是“桌子上同一时刻只能放其中1种组合“

如何实现

知识回顾与重要考点

九、读者-写者问题

问题描述

这里读进程与之前的消费者进程不同,消费者进程在消费一坨数据的时候,他会把这坨数据取走,也就是说消费者进程的操作是会影响数据的,但是读者进程与消费者进程不一样,,

问题分析

如何实现

如果在读进程中也和写进程一样单纯在读前P(rw)在读后P(rw)是不行的,这样会导致读进程与读进程之间也互斥,因此,我们使用count

又因为count的检查和赋值无法一气呵成,我们设置一个互斥信号量来保证各读进程对count的访问是互斥的

潜在的问题:假设当前系统中正在有一个读进程读文件,count的值为1,此时如果有一个写进程到,由于第一个读进程已经对rw进行P操作,所以rw现在是0,因此,写进程对rw进行P操作的时候会被阻塞;此时如果有读进程到来,由于此时count的值是1不等于0,所以这个读进程可以跳过rw的P操作,可以继续往下执行,读文件,同样地,如果有源源不断的读进程到来,都可以跳过这个P操作,都可以开始读文件,因此如果一直有读进程到来,由于只有最后一个读进程读完了后,这个rw信号量才会执行V操作,才会解锁,所以在最后一个读进程读完之前,这个写进程会一直被阻塞在rw,所以写进程可能“饿死”

因此,我们再设置一个互斥信号量w用于实现“写优先”

第一种情况,假设有两个读进程,如果第一个读进程在P(w)和V(w)之间发生了进程调度,切换成了第二个读进程,那么第二个读进程会被阻塞在P(w),直到第一个读进程执行了V(w),第二个读进程才能被唤醒,并且第二个读进程在P(mutex)和P(rw)处都不可能被阻塞。这样就保证了读进程1和读进程2可以同时读文件

第二种情况,假设有两个写进程并发运行,写进程1在写文件时w和rw都为0,那么写进程2肯定会被阻塞在P(w),直到写进程1执行了两个V。这样就保证了两个写进程之间的互斥写文件

第三种情况,一个写进程和一个读进程并发运行,假设刚开始上处理机运行的是写进程,当写进程正在写文件,w信号量的值为0,此时如果有读进程想要读文件,会阻塞在P(w)。这样就实现了写进程和读进程互斥访问文件

第四种情况,刚开始是一个读进程上处理机运行,当这个读进程在读文件时w的值等于1,此时如果切换成了写进程,由于w的值等于1,所以写进程在P(w)处不会被阻塞,但由于rw已经被第一个读进程执行了P操作,此时rw为0,因此写进程会在P(rw)处被阻塞,又由于此时写进程已经对w执行了P操作,因此w信号量此时为0,而不是1,所以如果此时还有一个读进程要上处理机运行,当它要对w进行P操作时,会被阻塞在P(w)下不去,这样的话写进程和后来的读进程都会被阻塞,只有读进程1可以顺利运行。读进程1读完文件后,对rw执行V操作,可以唤醒写进程,然后写进程写文件,与此同时,读进程2还在被阻塞
在增加了P(w)和V(w)这两个操作后,如果刚开始一个读进程先开始读文件,在它读文件的过程中,如果是读进程先于写进程到来,那么接下来是写进程先被唤醒,而只有当这个写进程写完文件并对w信号量执行V操作,它才会把读进程唤醒。这样就解决了写进程的饥饿问题。如果没有P(w)和V(w)这两个操作,当第二个读进程到的时候,管你此时有没有写进程在等待,我肯定都可以顺利地进行读文件

第五种情况,刚开始是一个写进程上处理机运行,写进行写文件时w和rw都为0,此时一个读进程来会被阻塞在P(w),此时如果还有第二个写进程上处理机运行,第二个写进程也会被阻塞在P(w),之前在信号量机制这个小节中,我们提过,信号量除了这个数字表示资源以外,还有一个排队的功能,由于这个读进程先对w进行P操作,所以这个读进程会排在w这个信号量的队头,第二个写进程会排在读进程之后,因此,在第一个写进程写完文件并对w进行V操作,它唤醒的其实是读进程,而不是之后到来的写进程,因为读进程排在w这个信号量的队头
可以看到这个算法并不是真正实现了“写优先”,而是相对公平的实现了先来先服务的原则

知识回顾与重要考点

十、哲学家进餐问题

问题描述

问题分析

这么做的问题在于,假如此时五个哲学家都并发地执行吃饭这件事情,每个哲学家都拿起了左边的筷子,但是当要拿右边筷子的时候,已经被别人给占用了,所以在执行右边筷子的这个P操作时,所有哲学家进程都会被阻塞,他们会循环等待自己右边的人放下筷子,这就出现了死锁,每个哲学家进程都阻塞地互相等待对方来释放资源,但是对于自己手里的资源来说,他们不会主动地把它放回去

如何实现

方法一:我们可以设置一个初始值为4的同步信号量
方法二:我们可以在每个哲学家拿筷子之前先判断一下他们的序号的奇偶性,再根据序号奇偶性来做下面具体的处理

我们来看方法三:

假设0号哲学家进程在尝试拿筷子,首先P(mutex)显然不会被阻塞,然后他拿到了左筷子,此时如果发生了切换,切换成了2号哲学家进程,当2号哲学家进程要P(mutex)操作时,由于0号哲学家还没有执行V(mutex),所以2号哲学家在执行P(mutex)时暂时会被阻塞,一直等到切换回0号哲学家并且他顺利地拿到右边筷子再V(mutex)操作之后,二号哲学家又可以被激活,然后可以顺利地执行下面的P操作
所以在一个哲学家左右两边的筷子都可以用的时候,他是可以一气呵成的拿起左右筷子的

第二种情况,假设刚开始0号哲学家进程拿完左右两个筷子然后V(mutex)之后吃饭,如果在这个时候1号哲学家也想吃饭,P(mutex)这个操作并不会把他阻塞,但当他尝试拿起左边的筷子时,他就会发生阻塞,而此时如果又发生调度,二号哲学家开始运行,他会尝试P(mutex)操作,也会被阻塞,在这种情况下,即使二号哲学家左右两个的筷子都能用,但是这个哲学家依然拿不起他左右的筷子,依然有可能会被阻塞

第三种情况,刚开始0号哲学家拿了左右筷子然后开始吃饭,然后4号哲学家拿起了左边筷子后,在尝试拿右边筷子时,已经被0号占用,4号哲学家就会被阻塞在右边筷子的P操作
虽然书上说“只有两边的筷子都可用时,才允许拿起筷子“,但其实即使一个哲学家两边的筷子其中某一边不能用的情况下,这个哲学家依然有可能拿起另一边的筷子,所以这种说法其实是不太严谨的
更准确的说法是,我们用mutex这个互斥信号量保证了每个哲学家拿筷子这件事都是互斥的进行的,如果一个哲学家正在拿筷子,不管是拿左边的还是拿右边,另一个哲学家就不允许同时来执行拿筷子这个操作。如果一个哲学家因为拿筷子被阻塞了,其他哲学家在尝试拿筷子时他连P(mutex)都过不了,会被阻塞在外面这层,既然这个哲学家被阻塞了,那么肯定有另一个哲学家手里持有他所需要的这个筷子,那只要这个哲学家吃完饭把筷子还到原位之后,这个哲学家就可以拿起他所需要的筷子顺利吃饭,然后再释放两个筷子,这样就可以避免循环等待发生死锁的现象

知识回顾与重要考点

十一、管程

为什么要引入管程

在引入管程之前,人们用来实现进程同步和互斥主要是使用信号量机制,也就是PV操作(比如消费者问题中如果实现互斥的P操作在实现同步的P操作之前,那么就有可能引起死锁的状态)

管程本质上也是用于实现进程的同步和互斥的

管程的定义和基本特征

拓展1:用管程解决生产者消费者问题

这里用的是类似于!c语言的代码来表述

如果有两个进程并发运行,并且先后都调用了管程的insert过程,那么由于刚开始没有任何一个进程正在访问这个管程中的某一个函数,所以第一个生产者进程在调用insert函数时是可以顺利地执行下去的,如果在第一个进程没有完这一个函数一系列逻辑时,第二个进程就尝试也想调用insert函数,那么由于编译器实现的这些功能,它会暂时阻止第二个进程进入insert函数,所以就会把第二个进程阻塞在insert函数后面,就类似于一个排队器等待,等第一个进程访问完了insert函数之后,才会让第二个进程开始进入insert函数执行相应一系列逻辑。所以其实互斥的使用某一些共享数据,这是由编译器负责为我们实现的,程序员写程序时不需要再关心如何实现互斥,只需要直接调用管程提供的这一系列方法,本身就可以保证这是互斥的进行的

除了互斥之外,管程还可以实现同步,我们可以在管程中设定一些条件变量,还有与他们对应的等待和唤醒操作,用来实现进程的同步问题

比如,如果有两个消费者进程先执行,生产者进行后执行,,第一个消费者进程需要执行wait等待操作,于是第一个消费者进程会等待在empty这个条件变量相关的这个队列当中,同样地,第二个消费者进程开始执行remove函数时也会发现此时count为0,它也需要执行这个等待操作,同样也会插入到empty这个条件变量对应的队尾。之后如果有一个生产者进程开始执行,它会执行管程的insert过程,会把自己生产的产品放到缓存区中,并且检查自己放入的产品是不是缓冲区中第一个产品,如果是第一个产品,意味着此时可能有别的消费者进程在等待我们的产品,所以接下来这个生产者进程在执行insert函数时也会在其中执行一个唤醒signal操作,用来唤醒等待在empty这个条件变量对应的等待队列中的某个进程,一般来说都是唤醒队头的这个进程,第一个消费者进程被唤醒后就开始执行,让count由1又变为0,再检查在取走产品前缓冲区是否已经满了,如果缓冲区之前已经是满的,就意味着有可能有生产者进程需要被唤醒,于是这个消费者进程又会调用一个对full这个条件变量的signal唤醒操作

拓展2:Java中类似于管程的机制

知识回顾与重要考点

王道考研——操作系统(第二章 进程管理)(进程的同步,进程的互斥,管程)相关推荐

  1. (王道408考研操作系统)第二章进程管理-第三节10:经典同步问题之哲学家进餐问题

    本文接: (王道408考研操作系统)第二章进程管理-第三节6:经典同步问题之生产者与消费者问题 ((王道408考研操作系统)第二章进程管理-第三节7:经典同步问题之多生产者与多消费者问题 (王道408 ...

  2. (王道408考研操作系统)第二章进程管理-第三节8:经典同步问题之吸烟者问题

    本文接: (王道408考研操作系统)第二章进程管理-第三节6:经典同步问题之生产者与消费者问题 ((王道408考研操作系统)第二章进程管理-第三节7:经典同步问题之多生产者与多消费者问题 文章目录 一 ...

  3. (王道408考研操作系统)第二章进程管理-第三节7:经典同步问题之多生产者与多消费者问题

    注意:生产者与消费者问题Linux系统编程专栏有案例讲解 Linux系统编程39:多线程之基于阻塞队列生产者与消费者模型 Linux系统编程40:多线程之基于环形队列的生产者与消费者模型 本文接:(王 ...

  4. 计算机组成原理笔记(王道考研) 第二章:数据的表示和运算1

    内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...

  5. 计算机组成原理笔记(王道考研) 第二章:数据的表示和运算2

    内容基于中国大学MOOC的2023考研计算机组成原理课程所做的笔记. 感谢LY,他帮我做了一部分笔记.由于听的时间不一样,第四章前的内容看起来可能稍显啰嗦,后面会记得简略一些. 西电的计算机组织与体系 ...

  6. (王道408考研操作系统)第二章进程管理-第二节4:调度算法详解2(RR、HPF和MFQ)

    文章目录 一:时间片轮转调度算法(RR) 二:优先级调度算法(HPF) 三:多级反馈队列调度算法(MFQ) 总结 进程调度算法也称为CPU调度算法,操作系统内存在着多种调度算法,有的调度算法适用于作业 ...

  7. (王道408考研操作系统)第二章进程管理-第一节4:进程通信(配合Linux)

    文章目录 一:什么是进程通信 二:如何实现进程间通信及其分类 三:通信方式1-共享存储(共享内存) (1)课本基础内容 (2)补充-Linux中的进程通信 四:通信方式2-管道 (1)管道是什么 (2 ...

  8. (王道408考研操作系统)第二章进程管理-第一节3:进程控制(配合Linux讲解)

    文章目录 一:如何实现进程控制 二:进程控制原语 (1)进程创建 A:概述 B:补充-Linux中的创建进程操作 ①:fork() ②:fork()相关问题 (2)进程终止 A:概述 B:补充-僵尸进 ...

  9. (王道408考研操作系统)第二章进程管理-第一节1:进程、PCB及其特征

    注意: 本章内容涉及进程,测试环境选在Linux下,因为我们可以阅读其源代码,有助于理解 Linux中的命令不会涉及太专业,需要说明的地方都会说明,读者只需关注其功能,无需过于操心原理 有兴趣的读者可 ...

  10. (王道408考研操作系统)第二章进程管理-第二节6、7:调度算法详解2(RR、HPF和MFQ)

    文章目录 一:时间片轮转调度算法(RR) 二:优先级调度算法(HPF) 三:多级反馈队列调度算法(MFQ) 总结 进程调度算法也称为CPU调度算法,操作系统内存在着多种调度算法,有的调度算法适用于作业 ...

最新文章

  1. 为什么科技互联网公司越来越重视数学?贾扬清等大牛如是说
  2. 数学分析原理 定理 6.4
  3. 2.innodb后台线程
  4. 开源 1 年半 star 破 1.2 万的 Dapr 是如何在阿里落地的?
  5. retrofit 会请求两次_Retrofit2+Rxjava-Rxjava2.x-篇二-依次执行多个请求-flatMap/map
  6. Java 接口和抽象类可以被new么?——顺便总结内部类
  7. Linux 网卡驱动学习(二)(网络驱动接口小结)
  8. 每日两道前端面试题20190226
  9. 3D世界相机防抖杆的机制探究
  10. 省级c语言笔试题,C语言笔试题库.doc
  11. 百度日语输入法快捷键(baidu type)
  12. 利用python爬虫进行彼岸网图库图片的抓取(bs4)
  13. 快速使用注解方式实现aop切面编程
  14. android 屏幕自动滚动效果,Android滑动屏幕效果
  15. 计算机课堂活跃小游戏,几个课堂小游戏(能活跃课堂气氛)
  16. 1.2什么是HLSL
  17. 萤石云设备下线是什么导致的_设备下线
  18. Java调用excel宏
  19. Python避免缩进错误
  20. Akka 指南 之「消息传递可靠性」

热门文章

  1. 如何监控服务器性能实践篇
  2. Lunece全文检索搜索引擎
  3. 版本 Version, Release, Build 和 Edition 之间的区别
  4. 提升活动现场互动氛围,微会动平台上线5款微信互动小游戏产品
  5. 星起航跨境—突破思维做跨境电商营销,实现企业转型
  6. 摄影师眼中的明基PD2710QC
  7. Selenium敏捷自动化测试
  8. 20180909_html_第三次_郑舒啸
  9. c语言 头文件卫士详解,C/C++中的“头文件卫士”
  10. SVD分解(python实现调用)