经典面试题-死锁

这篇具有很好参考价值的文章主要介绍了经典面试题-死锁。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.什么是死锁?

2.形成死锁的四个必要条件

3.死锁的三种情况

   第一种情况:

    举例:

     举例:

第二种情况:两个线程 两把锁

     举例:

第三种情况:N个线程 M把锁

哲学家进餐问题


1.什么是死锁?

        死锁是指在并发系统中,两个或多个进程(或线程)互相等待对方所占有的资源而无法继续执行的情况。这种情况下,每个进程都在等待其他进程释放资源,导致所有进程都无法向前推进。

2.形成死锁的四个必要条件

         1.互斥使用,获取锁的过程是互斥的。一个线程拿到了一把锁,另一个线程也想获取这把锁,就需要阻塞等待。

        2.不可抢占。一个线程拿到了锁之后,只能主动解锁,不能让别的线程强行把锁抢走。

        3.请求保持。一个线程拿到了锁A之后,在持有A的前提下,尝试获取B。

         4.循环等待:存在一个进程链,每个进程都在等待下一个进程所占有的资源。

3.死锁的三种情况

   第一种情况:

如果锁是不可进重入锁,并且一个线程对这把锁加锁了两次,那么它就会出现死锁的情况。

如果不是不可进重入锁。会出现下面的情况

    举例:

package 多线程;
//死锁
public class ThreadDemo15 {
    public static void main(String[] args) {
        Object locker =new Object();
        Thread t = new Thread(()-> {
            synchronized (locker) {
                synchronized (locker) {//当前由于事同一个线程,此时锁对象,就知道第二次加锁的线程,就是持有锁的线程。第二次操作会直接放行。
                    System.out.println("hello");
                }
            }//在这里解锁
        });
        t.start();
    }
}

它就会打印一个hello。 

经典面试题-死锁,java,操作系统,java,开发语言

 如果是不可重进入锁

     举例:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DeadlockExample {
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            lock.lock();
            System.out.println("Thread is holding the lock");

            // 尝试再次获取锁,会导致死锁
            lock.lock(); 

            System.out.println("This line will not be reached");
            lock.unlock();
        });

        thread.start();
    }
}

他就不会输出东西。

第二种情况:两个线程 两把锁

线程1 获取到 锁A

线程2 获取到 锁B

接下来,1 尝试获取B,2尝试获取A ,就会出现死锁。

一旦出现死锁,线程就会被卡住无法继续工作。

     举例:

package 多线程;
//死锁
public class ThreadDemo16 {
    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(()->{
            synchronized (A){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //A尝试获取B,并没有释放A
                synchronized (B){
                    System.out.println("t1 拿到了B");
                }
            }
        });
        Thread t2 = new Thread(()->{
            synchronized (B){//约定加锁顺序,
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (A){
                    System.out.println("t2 拿到了A");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

当我们输出结果就会发现它一直没有输出任何东西。 当t1线程持有A的锁资源时,它尝试获取B,而同时t2线程持有B的锁资源,它尝试获取A,这样两个线程相互等待对方的锁资源,导致死锁的情况发生。

经典面试题-死锁,java,操作系统,java,开发语言

         如何去解决这个问题呢,关键就在于死锁形成的四个必要条件,只要我们可以打破这四个必要条件,就不会形成死锁。这个题,我们约定好加锁的顺序的话,就不会出现死锁。

package 多线程;
//死锁
public class ThreadDemo16 {
    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(()->{
            synchronized (A){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //A尝试获取B,并没有释放A
                synchronized (B){
                    System.out.println("t1 拿到了B");
                }
            }
        });
        Thread t2 = new Thread(()->{
            synchronized (A){//约定加锁顺序,
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (B){
                    System.out.println("t2 拿到了A");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

        当t1线程获取到A对象的锁资源后,它会尝试获取B对象的锁资源,但是此时B对象已经被t2线程锁住了,因此t1线程会进入等待状态。当t2线程获取到B对象的锁资源后,它会尝试获取A对象的锁资源,此时A对象没有被锁住,因此t2线程可以获取到A对象的锁资源,执行完成后释放锁资源,然后t1线程才能继续执行,获取B对象的锁资源,避免了死锁的发生。 

 经典面试题-死锁,java,操作系统,java,开发语言

第三种情况:N个线程 M把锁

哲学家进餐问题

经典面试题-死锁,java,操作系统,java,开发语言

        描述了五位哲学家围坐在一张圆桌旁,每个人面前都有一碗米饭和一只筷子。这些哲学家只能用左手和右手各拿一只筷子进食。问题是,如何安排他们的动作,使得每个哲学家都能进餐?

问题分析 :

       由问题描述我们可以知道,一共有五个哲学家,也就是五个进程;五只筷子,也就是五个临界资源;因为哲学家想要进餐,必须要同时获得左边和右边的筷子,这就是要同时进入两个临界区(使用临界资源),才可以进餐。

 问题解决:

  1. 一次只允许两个哲学家进餐,并且要求他们都拿到右手边的筷子后才能开始进食。
  2. 引入一个仲裁者,即一个额外的实体负责协调哲学家的动作,以避免死锁的发生。
  3. 使用资源分配算法,例如Dijkstra的银行家算法,来确保每个哲学家都能有足够的资源进餐。

    希望大家多多支持! 经典面试题-死锁,java,操作系统,java,开发语言文章来源地址https://www.toymoban.com/news/detail-816243.html

到了这里,关于经典面试题-死锁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 操作系统-进程和线程-同步、互斥、死锁

    目录 一、同步互斥  二、互斥的实现方法 2.1软件实现 2.1.1单标志法 2.1.2双标志先检查 2.1.3双标志后检查 2.1.4Petersons算法 2.2硬件实现 2.2.1 TestAndSet指令 2.2.2 Swap指令   三、信号量机制 3.1整形变量  3.2 记录型变量  3.3用信号量实现进程互斥、同步、前驱关系 3.3.1互斥  3.3.2同步

    2024年02月08日
    浏览(52)
  • 操作系统进程线程(三)—进程状态、同步互斥、锁、死锁

    原子操作的概念 原子操作就是不可中断的一个或者一系列操作。 原子操作如何实现 总线锁定 使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号的时候,其他处理器的请求将被阻塞住,那么该处理器可以独占内存。 缓存锁 总线锁开销比较大,因为把CPU和内

    2024年02月04日
    浏览(52)
  • 操作系统实验二死锁避免之银行家算法的模拟

    死锁  (1)定义  (2)死锁产生的原因  (3)死锁产生的必要条件  (4)死锁的处理策略 银行家算法  (1)核心思想  (2)数据结构  (3)算法描述    (4)  安全性检查算法 银行家算法的模拟 (1)数据结构 (2)完整代码 (3)测试 所谓死锁,是指多个进程因为竞争资

    2024年02月01日
    浏览(65)
  • 【第三章 | 处理机调度与死锁】《操作系统 慕课版》课后答案 + 复习

    目录 【第三章】处理机调度与死锁 | 本章概念 1.处理机调度概述 2.调度算法相关概念 3.实时调度相关概念 4.死锁 5.资源分配图 | 本章算法 1.周转时间与带权周转时间的计算公式 2.调度算法 FCFS  SJF  PR  RR 3.实时调度算法 EDF 4.避免死锁 —— 银行家算法 | 课后简答题 1.处理机调

    2024年02月01日
    浏览(46)
  • 重读经典《操作系统:设计与实现》

    距离第一次阅读《操作系统:设计与实现》,已经是 20 多年了。当时,差不多是 2002 年吧,我已经参加工作了。我大学不是学计算机的,因而也没有上过操作系统的课。第一次去上海,在上海图书馆看到这本书(中文版),就买了回来,读了很多遍。现在,书好像找不到了,

    2024年03月09日
    浏览(54)
  • 经典面试题-死锁

    目录 1.什么是死锁? 2.形成死锁的四个必要条件 3.死锁的三种情况    第一种情况:     举例:      举例: 第二种情况:两个线程 两把锁      举例: 第三种情况:N个线程 M把锁 哲学家进餐问题         死锁是指在并发系统中,两个或多个进程(或线程)互相等待对方

    2024年01月22日
    浏览(41)
  • 经典面试题:谈谈对死锁的理解

    死锁是指在并发系统中,两个或多个进程(或线程)因为彼此互相等待对方释放资源而无法继续执行的状态。 简单来说 ,当多个进程都在等待其他进程所持有的资源时,就可能发生死锁。 当一个线程一把锁,连续加锁两次的时候,如果锁是不可重入锁,就会死锁 补充:C+

    2024年02月12日
    浏览(36)
  • 操作系统面试题

    存储器通过什么和CPU进行数据交互? 计算机存储数据寻址数据的内存单位是多少? 32位操作系统和64位操作系统到底什么区别? 任务调度 linux调度的对象是什么? task_struct 软中断和硬中断 应该先说硬中断再说软中断 什么是中断,中断是谁产生的,谁接收中断并进行什么操作

    2024年02月10日
    浏览(32)
  • 操作系统 面试第一弹

    进程(Process)和线程(Thread)是操作系统中的重要概念,它们表示执行中的程序的不同执行单元。下面是它们的区别: 定义:进程是一个独立的执行环境,具有独立的内存空间,包含程序代码、数据和执行状态。线程是进程内的一个执行单元,共享相同的内存空间和系统资

    2024年02月09日
    浏览(39)
  • C++面试题(叁)---操作系统篇

    目录  操作系统篇 1 Linux中查看进程运行状态的指令、查看内存使用情况的指令、 tar解压文件的参数。 2 文件权限怎么修改 3 说说常用的Linux命令 4 说说如何以root权限运行某个程序。 5 说说软链接和硬链接的区别。 6 说说静态库和动态库怎么制作及如何使用,区别是什么。

    2024年02月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包