如何避免死锁?

简介: 如何避免死锁?

8. 如何避免死锁?

从上图我们就可以看出,产生死锁就是俩个或多个线程在申请资源时,自己需要的资源别别人持有、并阻塞。所以导致死锁。

如何解决:

减小锁的范围,尽量保证之锁定自己需要的资源,减小交叉持有资源情况

但是有些时候不得不持有多个资源,比如银行转账,我们必须同时获得两个账户上的锁,才能进行操作,两个锁的申请必须发生交叉。这时我们也可以打破死锁的那个闭环,在涉及到要同时申请两个锁的方法中,总是以相同的顺序来申请锁,比如总是先申请 id 大的账户上的锁 ,然后再申请 id 小的账户上的锁,这样就无法形成导致死锁的那个闭环。

我们知道导致死锁有一个因素是阻塞,所以如果我们不使用默认阻塞的锁,也是可以避免死锁的。我们可以使用 ReentrantLock.tryLock() 方法,在一个循环中,如果 tryLock() 返回失败,那么就释放以及获得的锁,并睡眠一小段时间。这样就打破了死锁的闭环。

package com.roundyuan.fanggateway.test;

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

/**
 * @Author: JavaPub
 * @License: https://github.com/Rodert/
 * @Contact: https://javapub.blog.csdn.net/
 * @Date: 2022/1/2 14:38
 * @Version: 1.0
 * @Description: ReentrantLock
 */

public class DeadLock {

    private static Lock lock1 = new ReentrantLock();
    private static Lock lock2 = new ReentrantLock();

    public static void deathLock() {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    if (lock1.tryLock()) {
                        try {
                            //如果获取成功则执行业务逻辑,如果获取失败,则释放lock1的锁,自旋重新尝试获得锁
                            if (lock2.tryLock()) {
                                try {
                                    System.out.println("Thread1:已成功获取 lock1 and lock2 ...");
                                    break;
                                } finally {
                                    lock2.unlock();
                                }
                            }
                        } finally {
                            lock1.unlock();
                        }
                    }
                    System.out.println("Thread1:获取锁失败,重新获取---");
                    try {
                        //防止发生活锁
                        TimeUnit.NANOSECONDS.sleep(new Random().nextInt(100));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                while (true) {
                    if (lock2.tryLock()) {
                        try {
                            //如果获取成功则执行业务逻辑,如果获取失败,则释放lock2的锁,自旋重新尝试获得锁
                            if (lock1.tryLock()) {
                                try {
                                    System.out.println("Thread2:已成功获取 lock2 and lock1 ...");
                                    break;
                                } finally {
                                    lock1.unlock();
                                }
                            }
                        } finally {
                            lock2.unlock();
                        }
                    }
                    System.out.println("Thread2:获取锁失败,重新获取---");
                    try {
                        //防止发生活锁
                        TimeUnit.NANOSECONDS.sleep(new Random().nextInt(100));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            deathLock();
        }
    }
}

说起死锁,银行家算法非常有必要了解:

银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
1、操作系统按照银行家指定的规则为进程分配资源,当进程首次申请资源时,需要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请资源分配资源,否则就推迟分配;
2、当进程在执行中继续申请资源时,先测试该进程本次申请的资源数,是否超过了该资源剩余的总量,若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。


参考阅读:

如何快速排查死锁?如何避免死锁?

https://zhuanlan.zhihu.com/p/136294283

目录
相关文章
|
4月前
活锁与死锁
【8月更文挑战第22天】
82 4
|
4月前
|
Java
JUC(11)各种锁的理解(公平锁、可重入锁、自旋锁、死锁)
这篇文章介绍了Java并发包中的各种锁机制,包括公平锁与非公平锁、可重入锁、自旋锁以及死锁的概念、实现和示例,以及如何使用jps和jstack工具来检测和诊断死锁问题。
|
7月前
|
程序员
|
7月前
面试官:什么是死锁?死锁产生的原因?如何避免死锁?
面试官:什么是死锁?死锁产生的原因?如何避免死锁?
52 0
面试官:什么是死锁?死锁产生的原因?如何避免死锁?
|
Linux API C++
锁、避免死锁等相关
锁、避免死锁等相关
75 0
互斥锁的死锁
互斥锁的死锁
226 1
互斥锁的死锁
|
安全 Java
Java并发编程之Lock(同步锁、死锁)
这篇文章是接着我上一篇文章来的。
133 0
|
Java 编译器
Java多线程【锁优化与死锁】
Java多线程【锁优化与死锁】
Java多线程【锁优化与死锁】
多线程死锁的产生以及如何避免死锁
指多个线程因竞争资源而造成的一种僵局(互相等待),具体代码就是同步中嵌套了其他同步,这种现象称为死锁:比如过独木桥问题,其他锁还有可重入锁、可中断锁、公平锁和同步锁
183 0
|
Java
【多线程:活跃性】死锁、活锁、饥饿
【多线程:活跃性】死锁、活锁、饥饿
165 0