什么是死锁?(把死锁给大家讲明白,知道是什么,为什么用,怎么用)

死锁是多个线程因争夺资源而形成的僵局,彼此等待导致无法继续执行。产生死锁的原因包括互斥条件、占用并等待、不可抢占和循环等待。避免死锁的方法包括一次性申请所有资源、资源有序分配以及线程主动释放资源。提供的代码示例展示了两个线程因竞争不同资源而陷入死锁,修改资源对象为同一引用可解除死锁。
摘要由CSDN通过智能技术生成

3个方面回答 :

1.死锁是什么?

提供了几种理解的方式帮助大家更好的理解;如有疑问可提出;

死锁是一组相互竞争资源的线程因为他们之间得到互相等待导致“永久“阻塞的现象; (你等我 我等你 你不放我也不放 就导致“永久“阻塞的现象)

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

了解了说你是死锁后我们要知道为什么会发生死锁呢,请看下面;

2.发生死锁的原因?

分为下面4钟原因

互斥条件共享资源 X y 只能被一个线程占有
占用且等待线程T1占用的共享资源X 他在等待共享Y的时候帮不释放自己的X
不可抢占其他线程不能去抢占t1线程占有的资源
循环等待线程t1 等t2 占有的资源,线程t2 等t1占有的资源 循环等等

在这里插入图片描述

3.如何避免死锁?

打破死锁的原因即可避免

互斥条件无法破坏的因为锁本身就是通过互斥解决线程的安全的问题
占用且等待一次性申请所有的资源就不会存在等待了
不可抢占占用部分资源的线程,进一步申请其他的资源的时候如果申请不到可以主动释放他占有的资源,这样就破坏了不可抢占
循环等待按照顺序申请资源进行预防,所谓按序申请是指资源是有线性顺序的,申请的时候可以先申请资源序号小的 在申请资源序号大的 ,这样线性化循环就不存在等待了

在这里插入图片描述

下面我们用代码理解下死锁:

package com.example;

public class Deadlock {

       public static String str1 = "str1";
        public static String str2 = "str2";

        public static void main(String[] args){
            Thread a = new Thread(() -> {
                try{
                    while(true){
                        synchronized(Deadlock.str1){
                            System.out.println(Thread.currentThread().getName()+"锁住 str1");
                            Thread.sleep(1000);
                            synchronized(Deadlock.str2){
                                System.out.println(Thread.currentThread().getName()+"锁住 str2");
                            }
                        }
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            });

            Thread b = new Thread(() -> {
                try{
                    while(true){
                        synchronized(Deadlock.str2){
                            System.out.println(Thread.currentThread().getName()+"锁住 str2");
                            Thread.sleep(1000);
                            synchronized(Deadlock.str1){
                                System.out.println(Thread.currentThread().getName()+"锁住 str1");
                            }
                        }
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            });

            a.start();
            b.start();
        }
    }




上面的代码就是一个完整的死锁程序,程序中有两个线程,线程1锁住了str1,获得锁之后休眠1秒钟,这个时候线程2锁住了str2,也进行休眠操作。
线程1休眠完了之后去锁str2,但是str2已经被线程2给锁住了,这边只能等待,同样的道理,线程2休眠完之后也要去锁str1,同样也会等待,这样死锁就产生了。
在这里插入图片描述将下面这2行代码的值改成一样,就不会存在了

public static String str1 = "str1";
public static String str2 = "str1";

在声明一个对象作为锁的时候要注意字符串类型锁对象,因为字符串有一个常量池,如果不同的线程持有的锁是具有相同字符的字符串锁时,两个锁实际上同一个锁。

在这里插入图片描述

当多个哲学家围坐在一张圆形餐桌上时,每个哲学家需要交替地执行两个操作:思考和进餐。在每个哲学家的左右两边放置着一只餐叉,但是每只餐叉只能被相邻的两个哲学家之一使用。每个哲学家需要先拿起自己左边的餐叉,再拿起自己右边的餐叉,才能够进餐。在进餐时,哲学家需要保持持有的餐叉,直到进餐完成后才能放下。 哲学家进餐问题的目标是设计一种算法,使得每个哲学家都能够进餐,同时避免死锁和饥饿的发生。 然而,该问题存在的一种常见的错误解法是死锁。当每个哲学家都拿起了左边的餐叉时,他们都无法再拿起右边的餐叉,从而导致死锁。因此,必须设计一种算法,以确保进餐的过程中不存在死锁。 经典的解法是使用资源分配算法。一种简单的算法是,让每个哲学家先尝试获取其左边的餐叉,如果获取失败,则放弃左边的餐叉,等待一段随机的时间后再重试。如果成功获取左边的餐叉,则再尝试获取右边的餐叉。当一个哲学家成功获取了两只餐叉后,他才能够进餐。进餐完成后,哲学家需要放下两只餐叉,然后唤醒左右两侧的哲学家,让他们可以重新尝试获取餐叉。 这种算法可以确保进餐的过程中不会发生死锁,但是可能会导致饥饿。因为一个哲学家可能会一直等待,直到他能够同时获取到左右两只餐叉,而其他哲学家可能在这个哲学家等待的过程中进餐完成。因此,还需要进一步的改进算法,以减少饥饿的发生。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默 语

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值