操作系统之【死锁问题】

                                操作系统之【死锁问题】

一、什么是死锁?

         死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

二、死锁产生的条件?

2.1 互斥条件。

       指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

2.2 请求和保持条件

      进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程堵塞,但又对自己已获得的其他资源保持不放。

2.3 不剥夺条件

      指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

2.4 环路等待条件

        指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

三、来一个死锁的代码示例?

package com.soft;

public class Deadlock {

    public static void main(String[] args) {
        final Object a = new Object();
        final Object b = new Object();

        Thread threada = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
                    try {
                        System.out.println("现在 i threadA-lock-aaa");
                        Thread.sleep(1000l);
                        synchronized (b) {
                            System.out.println("现在 i threadA-lock-bbb");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread threadb = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (b) {
                    try {
                        System.out.println("现在 i threadB-lock-bbb");
                        Thread.sleep(1000l);
                        synchronized (a) {
                            System.out.println("现在 i threadB-lock-aaa");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        threada.start();
        threadb.start();
    }
}

代码执行结果:。

让我们来检查一下上面的代码,用到的JDK中自带的检查死锁的工具。

Jstack 命令 是Java虚拟机自带的堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。Jstack 用于生成Java虚拟机当前时刻的线程快照。线程快照是当前Java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。

(1)先通过 jps 命令确定当前执行任务进程号。

(2)Jstack -F 10340

如此我们可以得出结论

四、破坏死锁的方法

4.1 破坏互斥条件

方法:  如果允许系统资源都能共享使用,则系统不会进入死锁状态。

缺点:  有些资源根本不能同时访问,如打印机等临界资源只能互斥使用。所以,破坏互斥条件而预防死锁的方法不太可行,而且在有的场合应该保护这种互斥性。

4.2 破坏请求并保持条件

方法: 釆用预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行。一旦投入运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就可以保证系统不会发生死锁。

缺点: 系统资源被严重浪费,其中有些资源可能仅在运行初期或运行快结束时才使用,甚至根本不使用。而且还会导致“饥饿”现象,当由于个别资源长期被其他进程占用时,将致使等待该资源的进程迟迟不能开始运行。

4.3 破坏不可剥夺条件

方法: 当一个已保持了某些不可剥夺资源的进程,请求新的资源而得不到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。这意味着,一个进程已占有的资源会被暂时释放,或者说是被剥夺了,或从而破坏了不可剥夺条件。

缺点:该策略实现起来比较复杂,释放已获得的资源可能造成前一阶段工作的失效,反复地申请和释放资源会增加系统开销,降低系统吞吐量。这种方法常用于状态易于保存和恢复的资源,如CPU的寄存器及内存资源,一般不能用于打印机之类的资源。

4.4 破坏循环等待条件

方法: 为了破坏循环等待条件,可釆用顺序资源分配法。首先给系统中的资源编号,规定每个进程,必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源Ri,则该进程在以后的资源申请中,只能申请编号大于Ri的资源。

 缺点: 这种方法存在的问题是,编号必须相对稳定,这就限制了新类型设备的增加;尽管在为资源编号时已考虑到大多数作业实际使用这些资源的顺序,但也经常会发生作业使用资源的顺序与系统规定顺序不同的情况,造成资源的浪费;此外,这种按规定次序申请资源的方法,也必然会给用户的编程带来麻烦。

五、解决一个实际问题

系统有三个进程A、B、C。这三个进程都需要5个系统资源。当系统至少有多少个资源时,不可能发生死锁。

13个。因为当有13个资源的时候,可以在每个进程的时候先分配4个。一共会占据12个,剩下的一个资源可以分配给任意一个进程,此进程就可以完成他的任务,即释放他所占用的资源 。

k:进程数;n:每个进程占用的资源数;

公式:k * (n-1) +1

 

欢迎订阅关注公众号(JAVA和人工智能)

                                                           获取更多免费书籍、资源、视频资料 

           

文章超级链接:

 1,分布式系统详解--基础知识(概论)

 2,分布式系统详解--基础知识(线程)

 3,IDEA和Eclipse的比较

 4,IntelliJ IDEA(最新)安装-破解详解--亲测可用

 5,scala-构造器-辅助构造器-伴生对象-单例对象

 6,【由浅入深】爬虫技术,值得收藏,来了解一下~

 7,Akka 简介及简单原理

 8,Spark-集群安装、部署、启动、测试(1.6.3)稳定版

 9,Spark-RDD简介以及算子实例

10,分布式系统详解(Apache Hive 入门-简介)

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值