首页 > 其他分享 >死锁

死锁

时间:2023-06-12 15:15:08浏览次数:30  
标签:P1 Thread get 死锁 线程 资源

死锁

为什么会产生死锁?

只有理解了死锁为什么会产生,才能理解死锁产生需要的条件,同样死锁是一种现象,而不是一种机制.

死锁的出现其实是由于同步原语也就是各种同步机制所带来的,不可能做到百分百避免

  • 当有多个线程为了有限的资源竞争时,有的线程就会因为某一时刻没有空闲的资源而陷入等待.而死锁就是指这些线程都陷于等待其他线程释放资源而陷入了永久的等待.

例如:以下案例:

public class LockTest {
    private static Object resource1 = new Object();//资源 1
    private static Object resource2 = new Object();//资源 2
    public static void main(String[] args) {

        new Thread(() -> {
        synchronized (resource1) {
            System.out.println(Thread.currentThread() + "get " +
                    "resource1");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread() + "waiting get " +
                    "resource2");
            synchronized (resource2) {
                System.out.println(Thread.currentThread() + "get " +
                        "resource2");
            }
        }
            }, "线程 1").start();
        new Thread(() -> {
        synchronized (resource2) {
            System.out.println(Thread.currentThread() + "get " +
                    "resource2");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread() + "waiting get " +
                    "resource1");
            synchronized (resource1) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "get " +
                        "resource1");
            }
        }
 }, "线程 2").start();
    }
}
  1. 线程1先行获得资源1,线程2同样也获得资源2,这里为了模仿死锁,因此将线程睡眠大概1s,可以保证他两同时拿到各自的资源.

  2. 线程1/线程2想要获得对方的资源,但是由于资源1/资源2被保护了,互斥的缘故所以迟迟拿不到,因此双方会无限制地等下去

    • 因此,输出如下:

      Thread[线程 1,5,main]get resource1
      Thread[线程 2,5,main]get resource2
      Thread[线程 2,5,main]waiting get resource1
      Thread[线程 1,5,main]waiting get resource2
      

由此,我们再来观看死锁这一现象的性质,首先两个线程作为资源的持有者,除非自身放弃资源的拥有者身份,否则其他人绝对不可能获得,其次,资源获得的时候是互斥的,不允许多个线程同时获得,也就是锁的持有者只有一个人,另外,两个线程都会为了获取资源,而等待,他们本身不知道资源互斥的可能,因此等待的情况是前提,而这种双方互相等待的情景就形成了一个类似的环路.

所以,可以总结出来四个特点:

  1. 不可剥夺条件
  2. 互斥性
  3. 持有等待性
  4. 环路继续等待

图解表示就是这样的:

死锁

而死锁的预防也就比较明了了,根据那四个发生的条件:

既然不可剥夺条件,那么就允许被剥夺呗,但这样又会破坏锁的性质,通常来说锁的不可剥夺是一般不会轻易更改的,那么互斥性呢,既然要避免互斥访问,就意味着保护共享的资源呗,如果将线程a和线程b共同执行共享数据的代码提炼出来放在一个线程执行,也就是这种加锁解锁的执行顺序如果改变,即只可需要排队等待获取资源即可.那么持有等待呢?意味着持有的线程要去释放这一竞争资源,换个角度来说,竞争资源大概率会出现饥饿的情况,即很久都没有获取到资源,因此可以减少锁的时间,也就是只在必要的代码上加锁,尽量提前释放锁,另外环路继续等待本质上和死循环类似,因此要尽量避免循环的出现,尤其是有锁的代码区域.


死锁的避免(银行家算法)

死锁的避免设计思想其实就是每次线程去申请资源时都需要向系统提出申请,系统会根据状态,选择是否分配,而系统存在以下两种状态:

安全状态非安全状态,安全状态就是共享资源按照一定的序列去调度,就不会出现死锁的情况,因此被称为安全序列,而这个安全序列往往至少有1个.而如何去确定这个安全序列就是设计之点.

  • 银行家算法:这个算法的提出者可以说是老朋友了,因为数据结构里真的有很多算法(尤其是图的,我每次看都头疼),也就是Dijkstra这个人,读起来就知道他谁了.言归正传,他是通过模拟分配资源后的状态,来判断是否还处于安全的状态,也就是供需关系是否满足.

    因此:

    • 全局可利用资源
    • 每个线程的最大需求量
    • 已分配的资源数量
    • 还需要的资源数量

例如:假设有三个进程(P1、P2、P3)和三种类型的资源(R1、R2、R3),系统可用的资源数量为(10、5、7)。每个进程对资源的最大需求量和已分配资源量如下:

进程 最大需求量 (Max) 已分配资源量 (Allocation) 还需要的资源量 (Need)
P1 (7, 5, 3) (0, 1, 0) (7, 4, 3)
P2 (3, 2, 2) (2, 0, 0) (1, 2, 2)
P3 (9, 0, 2) (3, 0, 2) (6, 0, 0)

此时给P1,则可用资源数会变为(3,1,4),但等到P1完成后,系统可用的资源数 = (10,6,7),也就是原本的资源数+已分配资源量。而此时在分配给P2,还是P3都是可行的,因为在分配时比较需要的资源量是否足够,这是前提,其任务完成后进程也会释放相应的资源量,因此进程完成任务的顺序被称为安全序列,这道题,无论是{P1,P2,P3},{P2,P1,P3},{P3,P2,P1}都是可行的,如果此时可用资源为(5,5,7)则必须先执行P2释放相应的资源才能够执行P3,再执行P1,因此就只有一个安全序列{P2,P3,P1};

标签:P1,Thread,get,死锁,线程,资源
From: https://www.cnblogs.com/looktheworld/p/17475042.html

相关文章

  • MySQL数据库死锁问题
    参看:https://www.bilibili.com/video/BV1RT4y1R7bL/?spm_id_from=333.337.search-card.all.click&vd_source=46d50b5d646b50dcb2a208d3946b1598https://www.bilibili.com/video/BV1Sm4y1C7WX/?spm_id_from=333.337.search-card.all.click&vd_source=46d50b5d646b50dcb......
  • 操作系统(3.5.2)--计算机系统中的死锁
    1.竞争不可抢占性资源系统中所拥有的不可抢占性资源其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局。例如:系统中有两个进程P1和P2,它们都准备写两个文件F1和F2,而这两者都属于可重用和不可抢占性资源。进程P1先打开F1,然后再打开文件F2;进程P2先打开......
  • 死锁
    死锁的定义:多个进程相互等待对方资源,在得到所有的资源继续运行之前,都不会释放自己的资源,造成了循环等待的现象,称为死锁。死锁产生的必要条件:1.资源互斥:每一个资源只能给一个进程使用,资源不能共享使用。2.占有和等待:已经得到资源的进程还能继续申请新的资源。3.非抢占:当一个资源分......
  • 死锁编码与定位分析
    死锁编码与定位分析文章目录死锁编码与定位分析1.理论2.代码验证3.查找死锁故障1.理论死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相符待的现象,岩无外力干涉那它们都将无法推进下去。如果系统资源充足,过程的资源请求都能够得到满足,死锁出现的可能性就......
  • mysql死锁检查
    描述以下是一个shell脚本,用于检查MySQL死锁会话并杀死它们。它还将记录所有被杀死的会话及其相关的SQL到一个文件中。解决方案#!/bin/bash#设置MySQL连接参数MYSQL_USER="your_mysql_username"MYSQL_PASSWORD="your_mysql_password"MYSQL_HOST="localhost"MYSQL_PORT="......
  • 银行转账问题(死锁)
    本文主要讲述死锁的一个经典案例—银行转账问题,并对该问题进行定位、修复。1.问题说明当账户A对账户B进行转账时,首先需要获取到两把锁:账户A和账户B的锁。获取两把锁成功,且余额大于0,则扣除转出人的余额,并增加收款人的余额,而且这些操作都是在一个原子操作中获取锁的顺序相......
  • 哲学家就餐问题(死锁)
    本文主要讲述死锁的一个经典案例—哲学家就餐问题,并对该问题进行修复。1.问题描述看上图,有五位哲学家,每天循环做两件事:思考,吃面。吃面时每人面前都有一个盘子,盘子左边和右边都有一根筷子,他们在吃面之前需要先拿起左边的筷子再拿起右边的筷子,有了一双筷子就可以吃面了。具体......
  • 死锁细究
    一、死锁的定义&危害1、死锁是什么发生在并发中互不想让:当两个(或更多)线程(或进程)相互持有对方所需要的资源,又不主动释放,导致所有人都无法继续前进,导致程序陷入无尽的阻塞,这就是死锁。多个线程造成死锁的情况如果多个线程之间的依赖关系是环形,存在环路的锁的依赖关系,那么......
  • Oracle 死锁与慢查询总结
    查看死锁SELECTs.sid"会话ID",s.lockwait"等待锁",s.event"等待的资源/事件",--最近等待或正在等待的资源/事件DECODE(lo.locked_mode,0,'尚未获得锁',1,NULL,2,'行共享锁',3,'行排它锁',4,'共享表锁',5,'共享行排它锁',6,......
  • 死锁的产生及避免
    资料什么是死锁?死锁的产生条件及解决办法什么是死锁,死锁的原因及解决办法(含四个必要条件)死锁的产生原因与解决方法Java实例-死锁及解决方法实例产生死锁的四个必要条件:1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用2、不可抢占,资源请求者不能强制从资源占有者手......