操作系统——进程与线程(同步与互斥)

1)为什么要引入进程同步的概念?

2)不同的进程之间会存在什么关系?

3)单纯用本节知识解决问题时会遇到什么新问题吗?

一、同步与互斥

临界资源:

1)进入区:为了进入临界区使用临界资源,来检查是否能进入,若能进入就设置正在访问的临界区的标志,来阻止其他进程在同时刻进入临界区。

2)临界区:进程中访问临界资源的那段代码,又叫临界段。

3)退出区:将正在访问临界区的标志清楚。

4)剩余区:代码中的其余部分。

同步:直接制约关系。为了完成某种任务建立两个及以上的进程,来协调他们的运行次序和等待、传递信息产生的制约关系。(说人话,就是让不同进程排队,按照某种特定的顺序,不能把顺序弄混)

互斥:间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区后,另一个进程才允许去访问这个临界资源。

一个正在访问临界资源的进程(对一块临界资源上锁,这块临界资源不能被别的进程访问)由于申请等待I/O操作被中断(进入阻塞,处理机被释放给别的进程),那么它只允许其他进程抢占处理器,但不得进入该进程的临界区。

可重入编码:纯代码,不会修改任何变量的值。

共享程序段必须使用可重入编码编写,才可被安全的共享。

实现临界区互斥必须遵循的准则:

1)空闲让进:临界区空闲的时候可以允许一个请求进入临界区的进程立即进入临界区。

2)忙则等待:当以有进程进入临界区时,其他试图进入临界区的进程必须等待。

3)有限等待:对请求访问的进程,应保证能在有限时间内进入临界区,防止无限等待。

4)让权等待(不一定要遵守):当进程不能进入临界区时,应该立即释放处理器,防止进程忙等待。

二、实现临界区互斥的基本方法

1、软件实现方法

1)单标志法

turn = 0时p0允许进入临界区,turn = 1时允许p1进入临界区。

当对方一直不使用进入临界区,将turn改为我自己的话,那我自己就一直不能再次访问临界区,那么就违背了“空闲让进”原则。

2)双标志先检查法

用falg数组在进入临界区前,先检查对方是否想要进入临界区,若想,就等待;不想,就将falg[i]改成true后在进入临界区,退出时再改为false。

优点:不用交替进行,可以连续使用。

缺点:p0和p1可能同时进入临界区,按照下面例子进行可能会同时发生进程切换,结果双方检查都通过,违背“忙则等待”原则。原因在于检查和设置操作不是一气呵成的。

3)双标志后检查算法

先设置自己的标志,改为true,在检查对方的标志,若位true,就等待;否则,进入临界区。

但是若按照下面1,2,5,6执行,双方都抢着要进入临界区,结果谁都进不去,最后违背“空闲让进”,时间过长又会导致“饥饿”现象,违背“有限等待”原则。

4)Peterson算法

利用flag解决互斥问题,利用turn解决“饥饿”问题,双方都谦让着对方进入临界区,先设置自己falg=true,然后设置对方的turn进行谦让,最后再检查对方的while(falg[i]&&turn) 保证只有一个程序能进入,但是这样有一个程序执行时可能就会进行等待,违背了“让权等待”原则,但很好的遵循了“空闲让进”,“忙则等待”,“有限等待”。

turn变量表示轮到哪个线程进入临界区。

2、硬件实现方法

1)中断屏蔽方法

关中断:不允许当前进程被中断,也必然不会发生进程切换。

开中断:直到当前进程访问完临界区,才运行开中断,才有可能有别的进程上处理机并访问临界区。

2)TestAndSet指令(TSL)

1.若lock=false则表示没有进程在临界区,可以进入,并将lock置为true,对临界区加锁,其他进程不能进入临界区。

2.若lock=true,则表示有进程在临界区中,进入循环等待,直到当前访问临界区的进程退出时解锁,将lock置为false。

缺点:无法进入临界区的进程会占用CPU循环执行检查指令,不能实现“让权等待”。

3)Swap指令

跟TSL基本一样,就是实现方法不相同,优点缺点都一样。都是不能实现“让权等待”。

三、互斥锁

一个进程进入临界区调用acquire()获得锁,退出调用release()释放锁。

available=true,表示锁可用,否则就是不可用,进入阻塞,直到锁被释放。

四、信号量

信号量机制用来解决互斥和同步问题,只能被两个标准原语wait()和signal()访问,简称为P操作和V操作。

信号量机制:1.实现进程互斥。(互斥信号初值=1)2.实现进程同步。(同步信号量初值=0,前V后P,但一般来说,同步信号量初值是由用户决定的) 3.实现进程前驱关系(复杂的同步问题)

信号量的初值是资源的个数,信号量>=0时,初值 - 当前值 = 已进入临界区的数量。

信号量<0 时 绝对值 = 等待进入进程的数量。

上限M:最多M个进程可以进入该程序段,下限:最多N次P操作,为M - N

不需要信号量就能实现的功能是进程的并发执行,并发执行只需要有中断机制就可以。

原语:完成某种功能且不被分割、不被中断执行的操作序列,通常可以由硬件来实现。

           不可被中断的一小段程序,由“关中断”和“开中断”指令实现,是操作系统内核的一部分。是不可分割的指令序列。

前面的TSL和Swap指令就是由硬件实现的原子操作。

1)记录型信号量:

是一种不存在“忙等”现象的进程同步机制。

一次P操作,表示进程请求一个该类资源,S.value--。当S.value<0表示已经分配完毕,进入阻塞,主动放弃CPU;

一次V操作,表示进程释放一个该类资源,S.value++。

2)利用信号量实现进程互斥

进程互斥,一般来说都将mutex初值设为1

信号量是一个结构体

typedef struct{
    int value;

    struct process *L;

}semaphore;

3)利用信号量实现同步 (进程同步信号量的初值一般由用户决定,如消费者—生产者问题,里面缓冲区大小就是由用户决定empty大小)

同步源于进程之间的相互合作,需要让本来异步的并发进程相互配合,有序推进。进程间具有异步性。

4)利用信号两实现前驱关系

5)分析进程同步和互斥问题的方法步骤

1.关系分析,找出问题中断进程数,并分析他们之间的同步和互斥关系。

2.整理思路,根据进程的操作流程来确定P操作,V操作的大致顺序。

3.设置信号量。

五、经典同步问题

1.生产者—消费者问题 (用于解决多个进程之间同步和互斥问题)

由于缓冲区时临界资源,因此必须互斥访问。

前V后P;在前面那个动作完成之后要V(S)操作,释放;在后面动作开始之前要P(S)操作,申请。

该生产者—消费者:生产者要P一下申请一个空闲缓冲区,empty--,让空闲缓冲区数量减一,把产品放入缓冲区后就V一下,full++,增加一个产品的数量。当空闲缓冲区为0时,P操作这里进入阻塞队列。

到生产者,P一下申请消耗一个产品,full--,产品数量减少一个。V一下,增加一个空闲缓冲区,empty++,当产品数量为0时,P这里进入阻塞队列。

2.多生产者—多消费者问题

此时如果缓冲区大小>1 那就必须设置mutex来保证各个进程是可以互斥访问缓冲区的;否则,不同进程访问同一缓冲区,可能出现资源覆盖的情况。

但此问题中,缓冲区大小为1,盘子大小为一,只能放入一种水果,可以不用设置mutex,就可以保证程序之间是互斥的。

dad中,P检查盘子中可以放入多少个水果,V告知女儿苹果已经放入盘中。

daughter,P检查盘中是否由苹果,V告知父母盘子空了。

3.吸烟者问题

将每个人所需要的两种材料变成对应的组合,提供材料的人不断的提供材料,拿组合的人,P告诉它自己缺失材料,V表示自己已经抽完,再次需要材料提供。在if else语句中执行

4.读者—写者问题

不断增加P(w) V(w)和P(rw) V(rw)互斥信号量,其中有一个互斥访问计数器count,因此遇到一个不好解决的同步互斥问题,要想一想互斥访问计数器count是否能解决。

5.哲学家进餐问题

六、管程

管程中signal和V(S)操作不同 

相同点:都会唤醒阻塞程序;

不同点:V(S)会使信号量S=S+1,而signal不会改变条件变量的值

1)为什么要引入进程同步的概念?

为了协调进程之间的相互制约的关系。

2)不同的进程之间会存在什么关系?

同步和互斥的制约关系。

3)单纯用本节知识解决问题时会遇到什么新问题吗?

当两个或以上进程在执行过程中占有一些资源而又需要对方的资源时,会因为争夺资源而造成一种互相等待的现象,若无外力作用,他们都将无法推进下去,这种现象称为死锁。

两个线程分别对两个不同的互斥锁先后加锁,但顺序相反,那么就会死锁。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值