1.进程同步、进程互斥
1.1 进程同步
1.2 进程互斥
2.进程互斥的软件实现方法
2.1 单标志法
2.2 双标志先检查
2.3 双标志后检查
2.4 Peterson算法
3.进程互斥的硬件实现方法
3.1 中断屏蔽方法
3.2 TestAndSet(TS指令和TSL指令)
3.3 Swap指令
4.信号量机制
4.1 整形信号量
4.2 记录性信号量
4.3 信号量实现进程互斥
4.4 信号量实现进程同步
4.5 信号量实现进程的前驱关系
5.生产者、消费者问题
6.多生产者、多消费者问题
7.吸烟者问题
8.读者、写者问题
9.哲学家进餐问题
读进程和写进程并发地运行,由于并发必然导致异步性,因此“写数据”和“读数据”两个操作执行的先后顺序是不确定的。而实际应用中,又必须按照 “写数据一读数据”的顺序来执行的。如何解决这种异步问题,就是 “进程同步”所讨论的内容。
基本概念: 同步亦称直接制约关系,它只为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而产生制约关系。进程之间的直接制约关系就是源于它们之间的相互合作。
1.进程的“并发”需要“共享”的支持。各个并发执行的进程不可避免的需要共享一些系统资源(比如内存,又比如打印机、摄像头这样的I/O设备)
2.我们把一个时间段内只允许一个个进程使用的资源称为临界资源。许多物理设备(比如摄像头、打印机)都属于临界资源。此外还有许多变量、数据、内存缓冲区等都属于临界资源。
3.对临界资源的访问,必须互斥地进行,互斥,亦称间接的约束关系。进程互斥指当一个进程访问某临界资源时,另一个想访问该临界资源的进程必须等。当前访问临界资源的进程结束,释放该资源之后这个,另一个进程才能访问临界资源。
互斥访问临界资源,需要循序以下原则:
1.空闲等待。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区。
2.忙则等待。当已有进程进入临界区时,其他视图进入临界区的进程必须等待。
3.有限等待。对请求访问的进程,应保证能在有限时间内进入临界区(保证不会饿死)。
4.让权等待。当进程不能进入临界区时,应立即释放处理机,防止进程忙等待。
算法思想:
主要问题:
不遵循“空闲让进原则”
算法思想:
设置一个布尔型数组flag[],数组中个元素用来标记个进程想进入临界区的意愿,比如“flag[0] = true”意味着0号进程P0想要进入临界区。每个进程在进入临界区之前先检查当前没有别的进程想要进入临界区,如果没有,则把自身对应的flag[i]设为true,之后开始访问临界区。
主要问题:
若按照1、5、2、6、3、7…顺序执行,P0和P1都进入了访问临界区,因此违反“忙则等待”原则。
算法思想:
双标志先检查算法的改版。前一个算法的问题在于先“检查”后上锁,但是两个操作没办法一气呵成,因此导致了两个进程同事进入临界区的问题。因此人们想到了先“上锁”后 “检查”的方法。
主要问题:
若按照1、5、2、6的顺序执行,P0和P1都不能访问临界区,虽然解决了“忙着等待”的问题,但是违背了“空闲让进”和“有限等待”原则,会各进程都长期无法访问临界资源而产生“饥饿”现象。
算法思想:
双标志后检查法中,两个进程都争着想要进入临界区,但是谁都不让谁,最后谁都无法进入临界区。GrayL.Peterson想到了一个方法,如果双方都想争着进入临界区,那可以让进程尝试“孔融让梨”,主动的让对方先进入临界区。
主要问题:
不遵循“让权等待”原则,会发生“盲等”。
利用 “开/关中断指令” 实现(与原语的实现思想相同,即在某进程开始访问临界区到结束访问为止,都不允许被中断,也就 不能发生进程切换,因此也不可能发生两个同时访问临界区的情况)。
优点:
简单、高效。
缺点:
不适用于多处理机,只适用于操作系统内核进程,不适用于用户进程(因为开/关中断指令只能运行在内核态,这组指令如果能让用户随意使用会很危险)。
TSL 指令是用硬件实现的,执行的过程不允许被中断,只能一气呵成。以下是用C语言描述的逻辑
算法思想:
若刚开始lock是false,则TSL返回的old 值为false, while 循环条件不满足,直接跳过循环,进入临界区。若刚开始 lock是true,则执行TLS后old返回的值为true,while循环条件满足,会一直循环,直到当前访问临界区的进程在退出区进行 “解锁”。
相比软件实现方法,TSL指令把“上锁”和“检查” 操作用硬件的方式变成了一气呵成的原子操作。
优点:
实现简单,无需软件实现方法严格检查是否会有裸机漏洞,适用于多处理机。
Swap 指令是用硬件实现的,执行的过程不允许被中断,只能一气呵成。以下是用C语言描述的逻辑
算法思想:
逻辑上来看 Swap 和TSL并无太大区别,都是先记录下此时临界区是否己经被上锁(记录在old变量上),再将上锁标记 lock设置为true,最后检查old,如果old为false则说明之前没有别的进程对临界区上锁,则可跳出循环,进入临界区。
优点:
实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境。
缺点:
不满足 “让权等待”原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致“忙等”。
1.用户进程可以通过使用操作系统提供的一对原语来对信号量进行操作,从而很方便的实现了进程互斥、进程同步。
2.信号量其实就是一个变量(可以是一个整数,也可以是更复杂的记录型变量),可以用一个信号量来表示系统中某种资源的数量。,比如:系统中只有一台打印机,就可以设置一个初值为1的信号量。
3.原语是一种特殊的程序段,其执行只能一气呵成,不可被中断。原语是由关中断/开中断指令实现的。软件解决方案的主要问题是由 “进入区的各种操作无法一气呵成”,因此如果能把进入区、退出区的操作用原语来实现,是这些操作能“一气呵成”就能避免问题。
4.一对原语:wait(S) 原语和 signal(S) 原语,可以把原语理解为我们自己写的函数,函数名分别为 wait 和 signal,括号里的信号量S其实就是函数调用时传入的一个参数。
5.wait、signal 原语常简称为P、V操作(来自荷兰语 proberen 和 verhogen)。因此,做题的时候常把wait(S)、signal(S) 两个操作分别写为 P(S)、V(S)。
基本概念:
用一个整形的变量作为信号量,用来表示系统中某种资源的数量,这种变量区别于普通变量,对信号量的操作只有出事、P操作、V操作。
基本概念:
注:下面的P(S)操作 V(S) 无特别说明,都是记录性信号量。
1.分析并发进程的关键活动,划定临界区(如:对临界资源打印机的访问就应放在临界区)
2.设置互斥信号量mutex,初值为1
3.在临界区之前执行 P(mutex)
4.在临界区之后执行 V(mutex)
注意:
1.对不同的临界资源需要设置不同的互斥信号变量。
2.P、V操作必须成对出现。缺少P(mutex) 就不能保证临界资源的互斥访问。缺少 v(mutex)会导致资源永不被释放,等待进程永不被唤醒。
1.分析什么地方需要实现“同步关系”,即必须保证“一前一后”执行的两个操作(或两句代码)
2.设置同步信号量S,初始为0。
3.在“前操作”之后执行 V(S)。
4.在“后操作”之前执行 P(S)。
举例:下面要求在执行代码2操作执行了,代码4操作才能执行,所以只要在前操作之后执行一个V(S),在后后操作之前执行一个P(S)。
1.分析问题画出前驱图,把每对前驱关系都看成一个同步问题。
2.下面的步骤与上面的信号量实现进程同步一致。