浅谈死锁

浅谈死锁

死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进。死锁不仅仅是在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,而永久处于阻塞的状态。
这里写图片描述

下面是一个死锁的例子

/**
 * create by jingchao on 16:33
 */
public class DeadLock extends Thread {


    private String LockA;
    private String LockB;

    public DeadLock( String name,String lockA, String lockB) {
        super(name);
        LockA = lockA;
        LockB = lockB;
    }


    public void run() {
        synchronized (LockA){
            System.out.println(this.getName()+"持有了"+LockA);
            try {
                Thread.sleep(1000);
                synchronized (LockB){ System.out.println(this.getName()+"持有了"+LockB);
                }
            } catch (InterruptedException e) {
                // do nothing
            }
        }

    }


    public static void main(String[] args) throws InterruptedException {
        String LockA = "LockA";
        String LocKB = "LockB";
        DeadLock deadLock1 = new DeadLock("Thread1",LockA,LocKB);
        DeadLock deadLock2 = new DeadLock("Thread2",LocKB,LockA);
        deadLock1.start();
        deadLock2.start();
        deadLock1.join();
        deadLock2.join();

    }
}

这里写图片描述
可以看到此时两个线程相互等待对方所持有的锁,而发生了死锁状态。下面我们Dump Thread一下,看看线程的状态如何。
这里写图片描述

可以从图中看到,Thread1此时的状态为BLocked,Thread2也为Blocked,Thread2,等待的锁是<0x00000000d6cb9908>,而此时Thread1正持有该对象的锁,Thread1阻塞的原因是为了等待获取<0x00000000d6cb9940>,而该锁正在被Thread2所持有,故此,我们可以发现,Thread1和Thread2相互持有了对方所需要的锁,而发生了等待,形成了死锁。

如何在编程中尽量预防死锁呢?
首先,我们来总结一下前面例子中死锁的产生包含哪些基本元素。基本上死锁的发生是因为:

  • 互斥条件,类似 Java 中 Monitor 都是独占的,要么是我用,要么是你用。
  • 互斥条件是长期持有的,在使用结束之前,自己不会释放,也不能被其他线程抢占。
  • 循环依赖关系,两个或者多个个体之间出现了锁的链条环。

如何避免死锁?

  • 尽量避免使用多个锁,并且只有需要时才持有锁,嵌套的 synchronized 或者 lock 非常容易出问题。
  • 如果必须使用多个锁,尽量设计好锁的获取顺序,这个说起来简单,做起来可不容易,你可以参看著名的银行家算法。
  • 使用带超时的方法,为程序带来更多可控性。类似Object.wait(…)或者 CountDownLatch.await(…),都支持所谓的 timed_wait,我们完全可以就不假定该锁一定会获得,指定超时时间,并为无法得到锁时准备退出逻辑。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值