411操作系统学习笔记——进程与线程、处理机调度、同步与互斥(PV操作)、死锁(四)

简介: 411操作系统学习笔记——进程与线程、处理机调度、同步与互斥(PV操作)、死锁

3.11.哲学家进餐问题

有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。

约束条件

(1)只有拿到两只筷子时,哲学家才能吃饭

(2)如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子

(3)任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子

1.每个进程需要两个或者多个临界资源

2.①限制最多有4个哲学家进餐

semaphore cur = 4;    //表示当前最多还能允许几个人几餐
semaphore chopstick[5] = {1, 1, 1, 1, 1};
i() {    //第i个哲学家
    while(1) {
        P(cur);
        P(chopstick[i]);
        P(chopstick[(i + 1) % 5];
        进餐;
        V(chopstick[i]);
        V(chopstick[(i + 1) % 5];
        V(cur);
    }
}

用mutex实现对临界资源(拿筷子)的互斥访问:如果当前A正在进行拿左边筷子的操作,即A已经执行了P(mutex),但还未执行V(mutex),此时mutex = 0,若发生进程切换,切换到B后,将会阻塞在P(mutex),也就不会发生死锁,直到切换回A执行完V(mutex)后,B将会被唤醒

semaphore mutex = 1;    //互斥信号,用于实现一次仅能有一个人进行拿筷子的操作
semaphore chopstick[5] = {1, 1, 1, 1, 1};
i() {
    while(1) {
        P(mutex);    
        P(chopstick[i]);
        P(chopstick[(i + 1) % 5];
        V(mutex);
        进餐;
        V(chopstick[i]);
        V(chopstick[(i + 1) % 5];
    }
}

3.12.管程

1.管程用于实现进程的同步和互斥(与信号量作用相同,但更加方便)

2.管程是一种特殊的软件模块,由①②③④组成:(类似于类)

①局部于管程的共享数据结构说明(例如生产者和消费者模型中的缓冲区,可以通过数据结构表示该缓冲区,对该缓冲区进行管理;若使用,则需要定义一种与该缓冲区相对应的数据结构)

②对该数据结构进行操作的一组过程(过程可以理解为函数,即管程中需要有一组对①中数据结构进行操作的函数)

③对局部于管程的共享数据设置初始值的语句(管程中需要有对①中数据结构初始化的语句)

④管程需要有个名字

3.管程的基本特征:

①局部于管程的数据只能被局部于管程的过程所访问

②一个进程只有通过调用管程内的过程才能进入管程访问共享数据

每次仅允许一个进程在管程内执行某个内部过程(管程中虽然可能定义了很多个函数,但是同一时间只可能有一个进程在使用管程的某个函数,其余的进程若想执行管程的其他函数,需要等待该进程执行完该管程函数)

①②的意思是:管程中定义的数据结构只能被管程的函数修改,即想要修改管程中的数据需要调用管程的函数间接修改

③的作用是实现对缓冲区(临界资源)的互斥访问1ee7e369555349edbd49795567eab113.png8b4807da83b8403dafc8e5c7bbe721f3.png

4.死锁

4.1.死锁的概念

1.死锁:在并发环境下,各进程因抢占资源而造成的一种互相等待对方手里的资源,导致各进程都阻塞,无法继续执行的现象(每个进程都等待对方手里的资源,但是不放弃自己手里的资源,如果没有外力干涉,这些进程就无法继续向前推进)

2.死锁、饥饿、死循环的区别和联系:

19049c9458bf4c38a6b04633ab834c0d.png

3.死锁产生的必要条件:

互斥条件:只有对必须互斥使用的资源的争夺才会导致死锁的发生(哲学家的筷子);可以多个进程同时使用的资源不会发生死锁(内存)

不剥夺条件:进程所获得的资源在其使用完之前,不能由其他进程强行拿走,只能主动释放

请求和保持条件:进程已经至少持有一种资源的条件下,又申请了别的资源的请求,而该资源被其他进程所占有,此时请求进程被阻塞,但是对该进程已持有资源保持不放

循环等待条件:存在一种进程资源的循环等待链,链中的每一个进程已获得的资源同时被下一个进程所请求(例如哲学家问题中,若每个人都持有左边的筷子,都在等待右边的筷子)

同类资源 > 1时:发生死锁时一定有循环等待链,但有循环等待链不一定发生死锁(必要非充分条件);同类资源 = 1时,循环等待链的出现一定导致死锁的发生,死锁的发生一定有循环等待链(充分必要条件)

4.死锁的处理策略:

预防死锁:破坏死锁产生的四个必要条件中的一个或多个

避免死锁:用某种算法防止系统进入不安全状态,从而避免死锁(银行家算法)

死锁的检测和解除:允许死锁发生,操作系统会检测出死锁的发生,并且解除死锁  

ad02ca67df76407cabb8b6ad4a4386d7.png

4.2.预防死锁

1.破坏互斥条件:eb3dbca3f9044985af95030a90103691.png

2.破坏不剥夺条件:a6a312ee4371409e9753a375baaace81.png3.破坏请求和保持条件:导致饥饿是因为如果有源源不断的新的A类和B类进程,那么C类进程就将永远无法执行,即饥饿 1a460733887c41e2bb55b08fb4e222f4.png

4.破坏循环等待条件:

①实际使用资源的顺序可能和编号递增顺序不一致会导致资源浪费的原因:假设在实际使用过程中进程P3是先使用7号后使用5号,但根据编号递增顺序的要求,P3必须先申请使用5号,再申请使用7号,则在P3实际运行中5号某些时间是空闲的

②用户编程麻烦的原因:不同主机对不同设备的编号可能不同,但编号的不同会影响申请资源的顺序,即程序需要根据编号的不同而变化2eec89b75a33481d8234b46594e942ac.png

68709312bdb74552886cb3346dadd4ed.png

4.3.避免死锁(银行家算法)

1.安全状态→不会死锁(充分条件);死锁→不安全状态(不安全状态并不一定导致死锁)

2.只要有一个安全序列,就是安全状态(安全序列可能有多个)

3.银行家算法的思想:在资源分配前先预判这次分配是否会导致进入不安全状态,若会,则不进行此次分配‘若不会,则进行此次分配

cc91c145986941c2bfe3fdbf57f186ea.png

4.①找到(3,3,2)能满足的进程→P1、P3加入安全队列,并且将P1、P3已分配资源拿回→(7,4,3)

②找到(7,4,3)能满足的进程(除P1、P3外)→P0、P2、P4都可以→安全队列:P1、P3、P0、P2、P4(不唯一)7e4c8e22554f4e4d8bca1b766103cba9.png

126475b056204f22a340239c56793ca3.png

ea1a9ebce889461eb18b2814dd1e59b9.png

4.4.死锁的检测和解除

4.4.1.死锁的检测

1.进程结点(圆):一个结点对应一个进程

资源结点(矩形):一个结点对应一类资源,该结点中的一个小结点(矩形中的圆)对应该类资源的一个资源(三个小结点则表示该类资源共有三个)

请求边(进程指向资源的边):表示该进程对该类资源的请求,一条边对应一个资源

分配边(资源指向进程的边):表示该类资源对该进程已经分配了几个资源,一条边对应一个资源

2.如果能消除所有边,则一定不会发生死锁;如果不能消除所有边,则发生死锁

(1)可以消除所有边,即不会发生死锁:

P1向R2请求一个资源,P2向R1请求一个资源;R1给P1分配了两个资源,R2给P2分配了一个资源

①P2申请R1的1个资源,而R1此时没有剩余资源,因此P2阻塞e4bb3ad0252d4eb0b5658aaefa6d1652.png②R2剩余1个资源,可以满足P1的申请→P1执行完后,就可以将之前占用的两个R1归还4abcd29cd2874bbbb96121901aec3227.png

③R1剩余2个资源,可以满足P2的申请,即P1和P2的运行不会发生死锁

(2)不可以消除所有边,即发生死锁:

6ee4226a93d94b988f80a6ae4f581235.png

P1请求R2的两个资源,而R2的两个资源一个分配给P2,另一个分配给P3(P3的R2资源可以归还,但仍差一个);P2请求R1的一个资源,而R1的三个资源两个分配给P1,一个分配给R1,无空闲的R1资源,发生死锁

0c6f4eef12c94adb80f240b0b36a7a61.png

3.检测死锁的方法:

①在资源分配图中,找到既不阻塞(该点申请资源的数量可以满足它的需求,如P1)又不是孤点(该点至少与一个有向边相连,P1和P2都不是孤点)的进程:P1符合条件

b03be9ce339247f1a8779c97007ff7f1.png②消去该进程的所有请求边和分配边,使之成为孤点:消去P1所有的边,P1成为孤点f6e052d3dbd44a32b6a639d1d96cd98b.png

③消去该进程的边即释放该点的资源,因此,可以唤醒某些等待这些资源而被阻塞的进程:R1此时可以满足P2的申请,P2也可以消去所有的边,成为孤点

bf06940bf0c24ff2bb968531d69b86ec.png

④所有边都可以消去,则该图是可完全简化;若该图是不可完全简化,则系统死锁

4.4.2.死锁的解除faebde83387e4f6782f46dbdc2503bb8.png


53d9af92d4024336859a9e8ffc0bcd2c.png


相关文章
|
2月前
|
算法 调度 UED
深入理解操作系统:进程调度与优先级队列
【10月更文挑战第31天】在计算机科学的广阔天地中,操作系统扮演着枢纽的角色,它不仅管理着硬件资源,还为应用程序提供了运行的环境。本文将深入浅出地探讨操作系统的核心概念之一——进程调度,以及如何通过优先级队列来优化资源分配。我们将从基础理论出发,逐步过渡到实际应用,最终以代码示例巩固知识点,旨在为读者揭开操作系统高效管理的神秘面纱。
|
1月前
|
存储 算法 调度
深入理解操作系统:进程调度的奥秘
在数字世界的心脏跳动着的是操作系统,它如同一个无形的指挥官,协调着每一个程序和进程。本文将揭开操作系统中进程调度的神秘面纱,带你领略时间片轮转、优先级调度等策略背后的智慧。从理论到实践,我们将一起探索如何通过代码示例来模拟简单的进程调度,从而更深刻地理解这一核心机制。准备好跟随我的步伐,一起走进操作系统的世界吧!
|
2月前
|
消息中间件 算法 调度
深入理解操作系统:进程管理与调度
操作系统是计算机系统的核心,负责管理和控制硬件资源、提供用户接口以及执行程序。其中,进程管理是操作系统的重要组成部分,它涉及到进程的创建、调度、同步和通信等方面。本文将深入探讨进程管理的基本概念、进程调度算法以及进程间的同步和通信机制。通过本文的学习,读者将能够更好地理解操作系统的工作原理,并掌握进程管理的基本技能。
62 11
|
2月前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
操作系统作为计算机系统的核心,其进程管理和调度策略对于系统性能和用户体验至关重要。本文将通过直观的代码示例和浅显易懂的语言,带领读者了解操作系统如何有效管理进程以及常见的进程调度算法。我们将从进程的基本概念出发,逐步深入到进程状态、进程控制块(PCB)的作用,最后探讨不同的调度算法及其对系统性能的影响。无论您是初学者还是有一定基础的开发者,都能从中获得有价值的信息。
|
2月前
|
负载均衡 算法 调度
深入理解操作系统:进程管理与调度
在数字世界的心脏,操作系统扮演着至关重要的角色。它如同一位精明的指挥家,协调着硬件资源和软件需求之间的和谐乐章。本文将带你走进操作系统的核心,探索进程管理的艺术和调度策略的智慧。你将了解到进程是如何创建、执行和消亡的,以及操作系统如何巧妙地决定哪个进程应该在何时获得CPU的青睐。让我们一起揭开操作系统神秘的面纱,发现那些隐藏在日常计算背后的精妙机制。
|
2月前
|
调度 开发者
深入理解操作系统之进程调度
在计算机科学领域,操作系统是核心的一环,它管理着计算机硬件资源,并提供接口供上层软件运行。本文将通过深入浅出的方式,探讨操作系统中至关重要的一个概念——进程调度。我们将从基础理论出发,逐步展开讲解进程调度的原理和实现,并配以实际代码示例,旨在帮助读者更好地理解和掌握这一主题。文章不仅适合初学者建立基础,也适合有一定基础的开发者深化理解。
|
2月前
|
开发框架 Java .NET
.net core 非阻塞的异步编程 及 线程调度过程
【11月更文挑战第12天】本文介绍了.NET Core中的非阻塞异步编程,包括其基本概念、实现方式及应用示例。通过`async`和`await`关键字,程序可在等待I/O操作时保持线程不被阻塞,提高性能。文章还详细说明了异步方法的基础示例、线程调度过程、延续任务机制、同步上下文的作用以及如何使用`Task.WhenAll`和`Task.WhenAny`处理多个异步任务的并发执行。
|
2月前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
【10月更文挑战第40天】在数字世界中,操作系统是连接硬件与软件的桥梁,它管理着计算机资源和提供用户服务。本文将深入探讨操作系统中的进程管理与调度策略,揭示它们如何协调多任务运行,保证系统高效稳定运作。通过代码示例,我们将展示进程创建、执行以及调度算法的实际应用,帮助读者构建对操作系统核心机制的清晰认识。
|
2月前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
【10月更文挑战第34天】本文旨在探讨操作系统中至关重要的一环——进程管理及其调度策略。我们将从基础概念入手,逐步揭示进程的生命周期、状态转换以及调度算法的核心原理。文章将通过浅显易懂的语言和具体实例,引导读者理解操作系统如何高效地管理和调度进程,保证系统资源的合理分配和利用。无论你是初学者还是有一定经验的开发者,这篇文章都能为你提供新的视角和深入的理解。
47 3
|
2月前
|
算法 调度 UED
深入浅出操作系统调度策略
【10月更文挑战第33天】在数字时代的心脏,操作系统扮演着至关重要的角色。本文将探讨操作系统的核心功能之一——进程调度策略的设计与影响。我们将从理论到实践,通过浅显易懂的语言和具体代码示例,揭示如何通过不同的调度算法来优化系统性能和用户体验。无论你是技术新手还是资深开发者,这篇文章都将为你提供新的视角和深入的理解。