1. 什么是死锁 死锁的处理方法
在并发程序设计中,死锁 (deadlock) 是一种十分常见的逻辑错误。通过采用正确的编程方式,死锁的发生不难避免。
死锁的四个必要条件
在计算机专业的本科教材中,通常都会介绍死锁的四个必要条件。这四个条件缺一不可,或者说只要破坏了其中任何一个条件,死锁就不可能发生。我们来复习一下,这四个条件是:
•互斥(Mutual exclusion):存在这样一种资源,它在某个时刻只能被分配给一个执行绪(也称为线程)使用;
•持有(Hold and wait):当请求的资源已被占用从而导致执行绪阻塞时,资源占用者不但无需释放该资源,而且还可以继续请求更多资源;
•不可剥夺(No preemption):执行绪获得到的互斥资源不可被强行剥夺,换句话说,只有资源占用者自己才能释放资源;
•环形等待(Circular wait):若干执行绪以不同的次序获取互斥资源,从而形成环形等待的局面,想象在由多个执行绪组成的环形链中,每个执行绪都在等待下一个执行绪释放它持有的资源。
解除死锁的必要条件
不难看出,在死锁的四个必要条件中,第二、三和四项条件比较容易消除。通过引入事务机制,往往可以消除第二、三两项条件,方法是将所有上锁操作均作为事务对待,一旦开始上锁,即确保全部操作均可回退,同时通过锁管理器检测死锁,并剥夺资源(回退事务)。这种做法有时会造成较大开销,而且也需要对上锁模式进行较多改动。
消除第四项条件是比较容易且代价较低的办法。具体来说这种方法约定:上锁的顺序必须一致。具体来说,我们人为地给锁指定一种类似“水位”的方向性属性。无论已持有任何锁,该执行绪所有的上锁操作,必须按照一致的先后顺序从低到高(或从高到低)进行,且在一个系统中,只允许使用一种先后次序。
请注意,放锁的顺序并不会导致死锁。也就是说,尽管按照 锁A, 锁B, 放A, 放B 这样的顺序来进行锁操作看上去有些怪异,但是只要大家都按先A后B的顺序上锁,便不会导致死锁。
举例
假如有三个对象A、B、C,我们人为约定它们的锁序是: A 先于 B 先于 C。举例说来,下列锁序均为合法:
• 锁C,放C
• 锁B,放B
• 锁B,锁C,放B,放C
• 锁B,锁C,放C,放B
• 锁A,放A
• 锁A,锁C,放A,放C
• 锁A,锁C,放C,放A
• 锁A,锁B,放A,放B
• 锁A,锁B,放B,放A
• 锁A,锁B,锁C,放A,放B,放C
• 锁A,锁B,锁C,放C,放B,放A
而在上面定义的系统中,可能导致发生死锁典型上锁序列包括:
• 锁B,锁A,锁C,放C,放A,放B
(因为先B后A的上锁顺序违反了锁序约定,如果另一执行绪同时按照先A后B的顺序上锁,则可能由于执行绪甲获得了B,执行绪乙获得了A,而导致双方同时等待对方释放所持有的锁,从而形成死锁局面;解法是将操作序列中增加适当的锁操作,即改为锁B,放B,锁A,锁B,锁C,放C,放A,放B)
或者说,只要拿锁的时候不出现逆序(例如拿着C的时候试图抓B或A,或者拿着B的时候试图抓A),并出现潜在逆序的时候先放掉“小”锁再抓大的,就一定不造成死锁了。
2. 处理死锁的方法
预防死锁。这是一种较简单和直观的预先预防方法。该方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个来预防产生死锁。预防死锁是一种易实现的方法,已被广泛使用。
避免死锁。同样是属于事先预防策略,但它并不是事先采取各种限制措施,去破坏产生死锁的四个必要条件,而是在资源的动态分配过程中,用某种方法防止系统进入不安全状态,从而可以避免发生死锁。
检测死锁。这种方法无须事先采取任何限性制措施,允许进程在运行过程中发生死锁。但可通过检测机构及时地检测出死锁的发生,然后采取适当的措施,把进程从死锁中解脱出来。
解除死锁。当检测到系统中已发生死锁时,就采取相应的措施,把进程从死锁中解脱出来。常用的方法是撤消一些进程,回收它们的资源,将资源分配给已处于阻塞状态的进程,使其能继续运行。
3. 什么是死锁解决死锁有那几种策略这些策略分别有哪些实现方法
什么是死锁?如果一个进程集合里面的每个进程都在等待只能由这个集合中的其他一个进程(包括他自身)才能引发的事件,这种情况就是死锁。这个定义可能有点拗口,一个最简单的例子就是有资源a和资源b,都是不可剥夺资源,现在进程c已经申请了资源a,进程d也申请了资源b,进程c接下来的操作需要用到资源b,而进程d恰好也在申请资源a,那么就引发了死锁。这个肯定每个人都看过了。然后套用回去定义:如果一个进程集合里面(进程c和进程d)的每个进程(进程c和进程d)都在等待只能由这个集合中的其他一个进程(对于进程c,他在等进程d;对于进程d,他在等进程c)才能引发的事件(释放相应资源)。这里的资源包括了软的资源(代码块)和硬的资源(例如扫描仪)。资源一般可以分两种:可剥夺资源(preemptable)和不可剥夺资源(nonpreemptable)。一般来说对于由可剥夺资源引起的死锁可以由系统的重新分配资源来解决,所以一般来说大家说的死锁都是由于不可剥夺资源所引起的。死锁的四个必要条件互斥条件(mutual
exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(hold
and
wait):已经得到资源的进程可以再次申请新的资源。
非剥夺条件(no
pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
2.检测死锁并且恢复。
3.仔细地对资源进行动态分配,以避免死锁。
4.通过破除死锁四个必要条件之一,来防止死锁产生。
4. 操作系统的选择题答案
30.等待当前磁道上的某指定扇区旋转到磁头下所需的时间称为( A )
A.寻找时间 B.启动时间
C.延迟时间 D.传送时间
31.作业调度选中一个作业并把它装入主存,就为该作业创建一个进程,这个进程的初始状态为( D )
A.收容状态 B.就绪状态
C.执行状态 D.等待状态
32.能使平均周转时间最小的作业调度算法是( B )
A.计算时间短的作业优先算法 B.响应比最高者优先算法
C.优先数调度算法 D.均衡调度算法
33.引起一个进程从运行状态变为等待状态的原因可能是由于( A )
A.有更高优先级的进程就绪 B.某外围设备完成了指定的操作
C.进程调用了P操作 D.进程调用了V操作
34.在实现进程通信时会导致调用Send原语的进程被设置成“等信箱”状态的原因是
( D )
A.指定的信箱不存在 B.调用时没有设置参数
C.指定的信箱中无信件 D.指定的信箱中存满了信件
35.对资源采用按序分配的策略可以使产生死锁的______条件不成立。( D )
A.互斥使用资源 B.占有并等待资源
C.不可抢夺资源 D.循环等待资源
36.在下列解决死锁的方法中,属于死锁预防策略的是( A )
A.银行家算法 B.资源有序分配法
C.定时运行死锁检测程序法 D.资源分配图化简法
37.要求进程一次性申请所需的全部资源,是破坏了死锁必要条件中的( D )
A.互斥 B.请求与保持 C.不剥夺 D.循环等待
38.使用一个信号量协调6个进程对2个同类临界资源的访问,下列哪个信号量值不应该出现( A )
A.3 B.0 C.–1 D.–3
39.可执行程序存在于( C )
A.名空间 B.逻辑地址空间
C.储存空间 D.物理地址空间
40.从下列关于虚拟存储器的论述中,选出一条正确的论述。B
A.要求作业运行前,必须全部装入内存,且在运行中必须常驻内存;
B.要求作业运行前,不必全部装入内存,且在运行中不必常驻内存;
C.要求作业运行前,不必全部装入内存,但在运行中必须常驻内存;
D.要求作业运行前,不必全部装入内存,但在运行中必须常驻内存;
41.可解决文件重名问题的最简单的目录结构是( B )
A.单级目录 B.树型结构目录 C.二级目录 D.便于共享的目录
42.系统利用 SPOOLING技术实现(D )
A.对换手段 B.虚拟设备 C.系统调用 D.虚拟存储
5. 死锁定理是用于处理死锁的哪一种方法
死锁定理用于检测死锁。
系统处于死锁的充分条件是:当且仅当此状态的进程-资源分配图(是对当前状态的图形化描述)是不可完全简化的,这一充分条件称为死锁定理。由定理可知,这是一种检测方法。
6. 构成死锁的必要条件是什么如何检测死锁,解除死锁
死锁的四个必要条件
操作系统中有若干进程并发执行,它们不断申请、使用、释放系统资源,虽然系统的进
程协调、通信机构会对它们进行控制,但也可能出现若干进程都相互等待对方释放资源才能
继续运行,否则就阻塞的情况。此时,若不借助外界因素,谁也不能释放资源,谁也不能解
地等待永远不会发生的条件,系统处于停滞状态,这就是死锁。
产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。
死锁的解除与预防:
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。
7. 如何检测死锁并快速定位死锁位置
自动检测死锁的功能,如果发生死锁,会马上打印堆栈信息,并终止程序,如果是在调试环境中,会自动断点到发生死锁的地方。
实现思路如下:
比如Task A已经拥有了Lock 1,并准备去获取Lock 2,此时检测一下Lock 2是否被其它Task拥有了,如果没有,那Task A就很Happy的直接获取Lock 2就行了。如果Lock 2已经被Task B拥有了,那就检测一下Task B是否在等待Lock 1,如果是的话就说明是死锁了,此时打印一下堆栈信息,如果在调试环境,就中断调试,以方便查看死锁现场,否则直接退出程序。
这样虽然上锁的效率会降低,但很快就能发现死锁。一般发布游戏到线上的时候,就把死锁检测功能去掉,也不会影响性能。
看下我的测试代码:
TaskMutex mutex1;
TaskMutex mutex2;
void m1() {
try {
mutex1.lock();
sleep(1);
mutex2.lock();
mutex2.unlock();
mutex1.unlock();
} catch (...) {
std::cout << boost::current_exception_diagnostic_information() << std::endl;
}
}
void m2() {
try {
mutex2.lock();
sleep(1);
mutex1.lock();
mutex2.unlock();
mutex1.unlock();
} catch (...) {
std::cout << boost::current_exception_diagnostic_information() << std::endl;
}
}
int main(int argc, char *argv[]) {
try {
IoScheler scheler(2);
scheler.schele(boost::bind(&m1));
scheler.schele(boost::bind(&m2));
scheler.stop();
} catch (...) {
std::cout << boost::current_exception_diagnostic_information() << std::endl;
}
std::cout << "will exit.." << std::endl;
return 0;
}
8. 如何检查oracle死锁
oracle死锁问题一直困扰着我们,下面就教您一个oracle死锁的检查方法,如果您之前遇到过oracle死锁方面的问题,不妨一看。 一、数据库死锁的现象 程序在执行的过程中,点击确定或保存按钮,程序没有响应,也没有出现报错。 二、oracle死锁的原理 当对于数据库某个表的某一列做更新或删除等操作,执行完毕后该条语句不提交,另一条对于这一列数据做更新操作的语句在执行的时候就会处于等待状态,此时的现象是这条语句一直在执行,但一直没有执行成功,也没有报错。 三、oracle死锁的定位方法 通过检查数据库表,能够检查出是哪一条语句被死锁,产生死锁的机器是哪一台。 1)用dba用户执行以下语句 以下是代码片段: select username,lockwait,status,machine,program from v$session where sid in (select session_id from v$locked_object) 如果有输出的结果,则说明有死锁,且能看到死锁的机器是哪一台。字段说明: Username:死锁语句所用的数据库用户; Lockwait:死锁的状态,如果有内容表示被死锁。 Status: 状态,active表示被死锁 Machine: 死锁语句所在的机器。 Program: 产生死锁的语句主要来自哪个应用程序。 2)用dba用户执行以下语句,可以查看到被死锁的语句。 以下是代码片段:
9. 以下关于死锁问题的说法中正确的是
第四个正确
10. 死锁产生的4个必要条件,如何检测,解除死锁
死锁的四个必要条件
操作系统中有若干进程并发执行,它们不断申请、使用、释放系统资源,虽然系统的进
程协调、通信机构会对它们进行控制,但也可能出现若干进程都相互等待对方释放资源才能
继续运行,否则就阻塞的情况。此时,若不借助外界因素,谁也不能释放资源,谁也不能解
地等待永远不会发生的条件,系统处于停滞状态,这就是死锁。
产生死锁的原因主要是:
(1)
因为系统资源不足。
(2)
进程运行推进的顺序不合适。
(3)
资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1)
互斥条件:一个资源每次只能被一个进程使用。
(2)
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3)
不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4)
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。
死锁的解除与预防:
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。