操作系统——同步问题
什么是同步?
什么是临界区?
- 当一个进程在临界区内执行时,其他进程不允许在他们的临界区执行(即临界区内在一个时刻只能有一个进程)。
-
在进入临界区前,每个进程应当在进入区请求;当进程要退出临界区时,进程会进入到退出区。
临界区问题的解决方案应满足三个条件:
1)互斥:只能有一个进程在临界区内执行
2)进步:当有进程请求进入临界区时,应当在请求区中选择一个进程进入临界区,这种选择不能无限推迟
3)有限等待:保证请求进入临界区的进程在经历一段时间的等待后,会进入到临界区内
现在我们来简要介绍两种解决临界区问题的具体方法:1.互斥锁
- 互斥锁必须保证acquire函数和release函数的调用都是原子的。
需要忙等待(即进程要不断地执行循环代码),消耗大量的cpu时间。
优点进程在等待锁时,没有上下文切换。
2.信号量
用整型变量S表示剩余可进入临界区的进程数量(S的值根据S所代表资源的数量而定,一般设置为1);拥有两个原子操作wait()和signal(),即P和V操作。以S=1为例:进程首先执行wait()函数,先令S--;若S>=0,那么让该进程进入临界区;否则将该进程放入一个等待队列中等待被唤醒。当进程从临界区退出来时,执行signal()函数,令S++,如果S<=0,那么从等待队列中选择一个进程来唤醒(将其放到就绪队列的最前端);否则此时S=1,说明已经没有进程申请进入临界区,等待队列为空。
缺点上下文切换频繁。
不需要忙等待;如果无法进入临界区,将进程放进等待队列即可,cpu可以去服务其他进程。
经典同步问题
生产者-消费者问题(有限缓冲问题)
- 可以用信号量代表仓库的容量,利用互斥锁来解决同一时刻只能由一个生产者或消费者进入临界区这一问题;进入临界区之前首先判断进程是消费者还是生产者,当仓库为空时,消费者执行wait();当仓库为满时,生产者执行wait()。
读者-写者问题
- 1)允许多个读者同时读
- 2)读的时候不能写,写的时候不能读
- 3)多个写者不能同时写
第一读者-写者问题要求读者优先(即既有读者在排队,也有写者在排队,那么优先让排队的读者进入临界区);这可能导致写者饥饿。
哲学家吃饭问题
一个圆桌上,总共五个哲学家,五根筷子。当一个哲学家同时拥有左右两双筷子时,该哲学家才可以吃饭。当每一位哲学家都拿起同一侧的拿根筷子时,那么会出现死锁的现象,导致所有哲学家都占有且等待,无法进行吃饭。2)当一个哲学家可同时拿起左右两根筷子时,再拿起两根筷子进行吃饭;否则不拿筷子。这样解决了占有且等待(等待的不会占有)的问题,不会出现死锁现象。
3)采用非对称的拿筷子方式。单号哲学家首先拿起左边的筷子,再拿右边的筷子;双号哲学家首先拿起右边的筷子,再拿左边的筷子。这样可以保证相邻的两个哲学家必有一个可以吃到饭,解决了循环等待的问题,不会出现死锁现象。