操作系统第五章——进程同步

一、背景

对共享数据同步访问可能会造成数据的不一致性,要维护数据的一致性需要一个机制来保证协作进程的顺序访问。

竞争条件race condition:多个进程并发访问和操作同一数据,访问顺序会影响执行结果。

避免竞争条件——>进程需要同步。

 

二、临界区问题

(1)基本概念:

临界区Critical Section(CS):操作共享变量的代码区

进入区(entry section):请求进入临界区的代码段

退出区(exit section):临界区之后

剩余区(remanider section)(RS):其他代码

 

 

(2)解决临界区问题需要满足三个条件:

1.互斥(mutually exclusive)(ME)

如果已经有一个进程在临界区执行了,其他进程不能进入临界区;

<也就是说临界区代码最好短小精悍、没有无限的循环、进程在临界区等待时不能与其他进程通信>

2.前进(progress)

    没有进程在临界区,而且有进程请求进入临界区,那么这种请求不能被无限延迟

3.有限等待(bounded waiting)

    一个进程请求进入临界区被拒绝的次数有限(允许其他进程比它先访问的次数有限)

 

(3)解决临界区问题的三个方向:

1.Software solutions:算法的正确性不依赖其他假设

2.Hardware solutions:依赖特殊机器指令

3.Operating System solutions:通过系统调用提供一些函数和数据结构

 

三、具体解决方法——Software solutions

(1)主要的两种方法

1.Dekker’s Algorithm

比较复杂但是是正确的:

 

2.Peterson’s Solution

turn:谁可以进入临界区

flag:对应进程是否准备好想要进入临界区,准备好了就是true

 

 

(2)缺点

   脆弱、忙等、fail

1. 软件方法十分脆弱;

2. 存在busy waiting忙等(已经有了一个进程正处在某临界区内,其他任何试图进入这个临界区的进程都不得不进入代码连续循环,测试是否满足进入临界区的条件,浪费cpu资源);

3. 如果进程在临界区fail了,没有信号可以发送给其他进程。

 

四、具体解决方法——Hardware Solutions硬件同步

1.单处理器:可以使用禁止中断(中断屏蔽,屏蔽中断)对应非屏蔽中断  来实现,通常为非抢占内核采用;

2.多处理器:不采用禁止中断,原因:效率低;时钟

    (1)禁止中断效率太低:多处理器上要将消息传递给所有处理器——很费时,这种消息传递可能导致进入每个临界区都会延迟,进而降低了系统效率;

    (2)如果时钟是通过中断来加以更新的还会影响到系统时钟。

 

现代计算机提供了原子指令(不可中断的指令)

(1)锁locks

 

让进程在进入临界区之前先执行关中断指令”上锁“,保证了此后整个执行过程不会被中断,自然也不会发生进程切换、两个进程同时访问临界资源的情况,在访问完临界区之后,再通过开中断指令”解锁“,这样其它进程才有机会访问临界区。

涉及到了开/关中断这两个特权指令的使用,所以其实这种方法只适用于内核进程,不能用于用户进程。

 

(2)TestAndSet Instruction(spin lock自旋锁)

声明一个boolean变量lock,初始化为false,表示没有进程加锁了,每次执行TestAndSet指令都会使得target = true,直到有其他进程使得lock = false表示不再上锁,这样rv得到false的值才可以退出while循环,进入CS临界区,

TestAndSet()函数中的三条语句是由硬件保证同步的(硬件保证这三条语句必须原子运行,中间不发生任何中断,如同一条语句)

如果一个进程正在执行TestAndSet(),其他进程都不能执行TestAndSet()直到第一个进程结束。

 

(3)Swap Instruction

 

共享变量lock,初始化为FALSE;每个进程自己有一个本地变量key;

先将key设置为true,表示希望上锁,如果目前lock为false表示没有其他进程对临界区上锁了,swap指令会将key变为false,这样就可以退出循环进入临界区。

 

(4)优缺点

优点:单处理器和多处理机器都适用;简单高效;容易验证正确性;对多个进程可用;

缺点:busy-waiting忙等;饥饿(违背了有限等待,会产生饥饿现象)

(可以改进使得满足有限等待)

 

五、具体解决方法——OS Solution信号量semaphore

硬件的解决方法比较复杂,在操作系统层面可以使用信号量的同步工具,避免了忙等;

信号量S是一种整数变量。

(1)两个操作:wait()和signal()

 

wait(S)在S资源足够(大于零)的情况下,可以访问资源,故访问的资源数量减少1

signal(S)访问资源结束,资源重新空闲,资源数量增加1

(2)两种信号量:Counting和Binary

1.Counting用于实现同步;用来控制访问具有若干实例的某种资源。

2.Binary用于实现互斥,只能取0/1,也叫互斥锁,常用mutex(mutual exclusion作为变量名)

 

(3)实现

要保证没有两个进程可以同时对同一信号量执行wait()和signal(),单处理器用禁止中断来实现,多处理器需要禁止每一个处理器的中断,但这样效率低,所以需要提供其他加锁技术。

 

克服忙等的信号量实现:当一个进程执行wait()操作时,发现信号量值不为正,不能进入临界区,则将这个进程阻塞block(),放入与这个信号量相关的等待队列里面,将进程状态切换为等待,不让它忙等,直到其他进程执行了signal()操作后它可以被重新执行wakeup(),将该进程从等待状态切换到就绪状态。

两种操作:block()和wakeup()

在这种情况下wait()和signal()的定义如下:

 

(3)死锁和饥饿

1.死锁:两个或者多个进程无尽的等待一个资源,而这个资源只能由等待的进程之一来产生。

2.饥饿:(无限期阻塞)进程在信号量内无限期等待,例如与信号量相关的链表按照LIFO顺序来移动和增加进程。

 

六、经典同步问题(三大问题)

(1)生产消费者问题   有限缓冲问题Bounded-Buffer Problem

资源有很多个???

N buffers每个可以存一个数据项;Semaphore mutex初始化为 1;

counting信号量full和empty

Semaphore full初始化为 0;记录放得有物品的缓冲槽数目

Semaphore empty 初始化为N;记录空的缓冲槽数目

       

生产者进程和消费者进程的代码是对称的,生产者为消费者生产满缓冲项full,消费者为生产者生产空缓冲项empty

       伪代码中需要强调条件变量在前,互斥锁在后,否则会出现死锁。

因为可能拿到了互斥锁,但是却不满足继续运行条件,但要满足继续运行条件需要另一个进程拿到互斥锁来给他产生条件,但因为互斥锁被拿了,所以另一个进程无法进行。

 

 

(2)读者-写者问题Readers and Writers Problem

    读者之间不互斥,写者和读、写都互斥。

    互斥信号量mutex,初始化为1,表示读者对readcount的访问互斥;

    互斥信号量wrt,初始化为1,表示读写互斥,写写互斥;

    整数readcount,初始化为0,记录当前在读的读者数目;

写者进程结构:

 

读者进程结构:

 

这里的代码是第一读者-写者

 

    第一读者-写者问题,读者优先级高;

    第二读者-写者问题,写者优先级高;

公平竞争

 

(3)哲学家就餐问题Dining-Philosophers Problem

如果用下面这种算法会产生死锁,五个哲学家同时wait(chopstick[i])成功,每个人都只能拿到一只筷子。

 

解决方法:

1.一次只允许最多四个哲学家拿筷子,初始化T.count := 4

2.如果想给某个哲学家筷子,就将他需要的所有资源都给他,然后让他进餐,否则就一个都不给他。

3. 奇数号哲学家先拿起他左边的筷子,然后再去拿他右边的筷子,而偶数号的哲学家则相反,这样的话总能保证一个哲学家能获得两根筷子完成进餐,从而释放其所占用的资源

七、管程Monitor(不考)

(1)概念

因为信号量的使用顺序十分重要,必须保证顺序,不然可能会出现两个进程同时在访问一个临界区的情况,为了处理这种错误引入一种高级语言构造——管程类型。

额外的同步机制——条件变量condition类型的变量,condition x,y

条件变量有两种操作:

1.x.wait()调用操作的进程会挂起,直到另一个进程调用x.signal()

2.x.signal()重新启动一个之前挂起的进程,如果没有进程悬挂(挂起)则这个操作没有作用。

(2)用管程来解决哲学家就餐问题

定义一个管程dp(DiningPhilosophers)

则哲学家i的操作如下:

dp.pickup(i);

...

eat

...

dp.putdown(i);

这一解决方法保证了相邻两个哲学家不会同时用餐,而且不会出现死锁,但是有可能会出现饿死。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值