草庐IT

浅谈对死锁的理解

杏花烟雨湘兰 2023-04-03 原文

死锁是多线程编程中的一个常见问题,它会导致程序停滞不前,无法继续执行下去。在实际开发中,死锁问题可能会导致程序崩溃,影响系统的稳定性和可靠性。

死锁是指两个或多个线程在互相等待对方释放资源的情况下,都无法继续执行下去的现象。死锁通常具有四个特点:互斥、占有并等待、不可剥夺和循环等待。

  • 互斥条件:至少有一个资源是排他性的,即一次只能被一个进程使用。

  • 占有并等待条件:进程已经占有至少一个资源,并且在等待另一个被其它进程占用的资源。

  • 非剥夺条件:进程占有的资源不能被强行剥夺,只能在使用完后自愿释放。

  • 循环条件:存在一种进程资源的环形等待链,每个进程都等待下一个进程所占有的资源。

举个栗子:相信大家小时候都有看过《喜羊羊与灰太狼》,在古古怪界大作战中,想要进入古古怪界就需要将阴离子球和阳离子球合二为一来打开通往地底世界的大门

 已知需要两个离子球合二为一才能进入地底世界,那么我们假设现在灰太狼手中掌握着阴离子球,而慢羊羊手中掌握着阳离子球(请不要在意字幕)

 那么我们目前的状况是:

1.慢羊羊和灰太狼都不愿意和对方分享离子球(互斥条件)

2.慢羊羊和灰太狼都占有了一个离子球,并且都在等待对方放弃手中的离子球(占有并等待)

3.离子球是打开古古怪界的钥匙的同时也是强力的武器,慢羊羊和灰太狼都无法强行抢夺对方的离子球(非剥夺)

4.灰太狼在等待慢羊羊的阳离子球,慢羊羊也在等待灰太狼的阴离子球,形成了一个循环(循环)

那么可想而知下一步的发展,慢羊羊和灰太狼谁也无法将阴阳离子球合二为一,打开古古怪界的大门,局面就会这样僵持住

那么我们如果将两个离子球比作资源,将灰太狼和慢羊羊看作两个线程,这种僵持的局面就可以看作死锁了,即两个或更多线程,需要占有彼此的资源才能继续运行,然而因为资源被对方占有,它们都无法剥夺对方的资源,这样几个线程就都无法继续执行,形成了僵持的局面,这便是死锁

下面我们通过Java来实现一下这种死锁的产生

public class Demo {

    private static Object lock1 = new Object();//阴离子球
    private static Object lock2 = new Object();//阳离子球

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {//灰太狼
            synchronized (lock1) {
                System.out.println("灰太狼持有阴离子球");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                }
                System.out.println("灰太狼正在等待阳离子球");
                synchronized (lock2) {
                    System.out.println("灰太狼同时得到了两个离子球,开启古古怪界的大门");
                }
            }
        });

        Thread t2 = new Thread(() -> {//慢羊羊
            synchronized (lock2) {
                System.out.println("慢羊羊持有阳离子球");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                }
                System.out.println("慢羊羊正在等待阴离子球");
                synchronized (lock1) {
                    System.out.println("慢羊羊同时得到了两个离子球,开启古古怪界的大门");
                }
            }
        });

        t1.start();
        t2.start();
    }
    
}
   
在上述代码中,我们定义了两个线程分别代表慢羊羊和灰太狼,定义两个Object类分别代表阴离子球和阴离子球,让两者持有各自的离子球之后睡眠10ms来保证双方各自持有一个离子球的初始条件。      

        接下来我们分别启动两个线程

 我们可以看到两个线程谁也无法获得对方所持有的锁,这便形成了死锁的局面。

有关浅谈对死锁的理解的更多相关文章

  1. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  2. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  3. ruby - 易于初学者理解的 Ruby 库 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5

  4. ruby - 无法理解 `puts{}.class` 和 `puts({}.class)` 之间的区别 - 2

    由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A

  5. ruby - 如何理解 Ruby 中的发送者和接收者? - 2

    我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo

  6. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

  7. 智能客服 | 浅谈人工智能聊天机器人ChatGPT - 2

    2022年底,OpenAI的预训练模型ChatGPT给人工智能领域的爱好者和研究人员留下了深刻的印象和启发,他展现的惊人能力将人工智能的研究和应用热度推向高潮,网上也充斥着和ChatGPT的各种聊天,他可以作诗、写小说、写代码、讨论疫情问题等。下面就是一些他的神回复:人命关天的坑: 写歌,留给词作者的机会不多了。。。 回答人类怎么样面对人工智能: 什么是ChatGPT?借用网上的一段介绍,ChatGPT是由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型,一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动

  8. ruby - 使用 SizedQueue 在 ruby​​ 代码中出现死锁 - 2

    我认为我对线程在ruby​​中的工作原理存在根本性的误解,我希望获得一些见解。我想要一个简单的生产者和消费者。首先,生产者线程从文件中提取行并将它们粘贴到SizedQueue中;当那些用完时,在末端贴上一些token,让消费者知道事情已经完成。require'thread'numthreads=2filename='edition-2009-09-11.txt'bq=SizedQueue.new(4)producerthread=Thread.new(bq)do|queue|File.open(filename)do|f|f.eachdo|r|queue现在有几个消费者。为简单起见,让

  9. ruby - 你如何理解 Ruby 中的这个三元条件? - 2

    我在某些代码中遇到了三元组,但我无法理解条件:str.split(/',\s*'/).mapdo|match|match[0]==?,?match:"somestring"end.join我确实理解我是在某些点上拆分字符串并将总结果转换为数组,然后依次处理数组的每个元素。除此之外,我不知道发生了什么。 最佳答案 一种(稍微)不那么令人困惑的写法是:str.split(/',\s*'/).mapdo|match|ifmatch[0]==?,matchelse"somestring"endend.join我认为多行三元语句很糟糕,尤其是

  10. ruby - 您如何将 S3 理解为 Ruby 中的分层目录结构? - 2

    有没有人成功地将S3存储桶读取为子文件夹?文件夹1--子文件夹2----文件3----文件4--文件1--文件2文件夹2--子文件夹3--文件5--文件6我的任务是读取文件夹1。我希望看到子文件夹2、文件1和文件2,但看不到文件3或文件4。现在,因为我将存储桶键限制为prefix=>'folder1/',你仍然会得到file3和4,因为它们在技术上具有folder1前缀。似乎真正做到这一点的唯一方法是吸收folder1下的所有键,然后使用字符串搜索从结果数组中实际排除file3和file4。有没有人有过这方面的经验?我知道像Transmit和Cyber​​duck这样的FTP风格的S3

随机推荐