Java实现死锁

本文通过一个具体的Java示例,详细解析了多线程环境下如何产生死锁现象。两个线程分别获取不同对象的锁后,试图获取对方持有的锁,从而形成相互等待的状态,导致程序无法继续执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在多线程中,为了保证数据等准确性和一致性,一般在进行共享数据进行操作等时候,我们都会进行加锁,保证同一时间只有一个线程在操作这个对象。由于加锁的原因,如果一不注意的话很容易导致死锁。死锁的原因是两个线程或者多个线程在互相等待对方释放资源,一直在阻塞等待,这就造成了死锁。由于Java中没有对死锁进行监管的东西,在死锁中,线程会一直被阻塞,程序不会有任何提示的消息,也无法继续下去。

下面是一个死锁的例子,可以帮助大家理解死锁的机制:

package lock;

/**
 * Created by pozhen on 17/2/12.
 * 1.首先开启一个线程(副线程),启动线程后,会先进入run方法,run方法执行b.hold(a)方法,给b对象加了锁,然后休眠200ms
 * 2.然后主线程几乎是和副线程同时,但是会慢上一些进入init()方法,然后执行a.hold(b)方法,给a对象加了锁,然后休眠200ms
 * 3.b对象会提前结束休眠,将要执行代码4,需要给a对象加锁,但是现在a对象的锁被副线程持有,所以主线程阻塞,等待副线程释放a对象的锁。
 * 4.这时候副线程的休眠也结束了,将要执行代码2,需要给b加锁,但是现在b对象的锁被主线程持有,所以副线程阻塞,等待主线程释放b对象的锁。
 * 5.最后,主线程阻塞在等副线程释放锁,副线程也在阻塞等待主线程释放锁,这时候就一直等待下去,无穷无尽,这就造成了死锁。
 */
public class DeadLockExample implements Runnable{

    class A {
        public synchronized void hold(B b) {
            try {
                System.out.println(Thread.currentThread().getName()+"目前持有A的锁");//代码1
                Thread.sleep(200);
            }catch (Exception e) {
                e.printStackTrace();
            }
            b.last();
        }

        public synchronized void last() {
            System.out.println(Thread.currentThread().getName()+"的A对象企图访问B对象的last方法,准备要给B对象加锁");//代码2
        }
    }

    class B {
        public synchronized void hold(A a) {
            try {
                System.out.println(Thread.currentThread().getName()+"目前持有B的锁");//代码3
                Thread.sleep(200);
            }catch (Exception e) {
                e.printStackTrace();
            }
            a.last();
        }
        public synchronized void last() {
            System.out.println(Thread.currentThread().getName()+"的B对象企图访问A对象的last方法,准备要给A对象加锁");//代码4
        }
    }

    A a = new A();
    B b = new B();

    public void init() {
        Thread.currentThread().setName("主线程");
        a.hold(b);
    }

    @Override
    public void run() {
        Thread.currentThread().setName("副线程");
        b.hold(a);
    }

    public static void main(String[] args) {
        DeadLockExample deadLockExample = new DeadLockExample();
        new Thread(deadLockExample).start();
        deadLockExample.init();
    }
}
银行家算法是一种避免死锁的经典算法,它主要用于分配有限的资源,以避免出现死锁的情况。下面是Java实现死锁避免银行家算法的示例代码: ```java import java.util.Scanner; public class BankerAlgorithm { private int[][] need; // 还需要的各类资源 private int[][] allocate; // 已分配的各类资源 private int[] available; // 可用的各类资源 private int[] safeSequence; // 安全序列 public void init() { Scanner scanner = new Scanner(System.in); System.out.println("请输入进程数量:"); int processCount = scanner.nextInt(); System.out.println("请输入资源种类数量:"); int resourceCount = scanner.nextInt(); need = new int[processCount][resourceCount]; allocate = new int[processCount][resourceCount]; available = new int[resourceCount]; safeSequence = new int[processCount]; System.out.println("请输入每个进程需要的各类资源:"); for (int i = 0; i < processCount; i++) { for (int j = 0; j < resourceCount; j++) { need[i][j] = scanner.nextInt(); } } System.out.println("请输入每个进程已分配的各类资源:"); for (int i = 0; i < processCount; i++) { for (int j = 0; j < resourceCount; j++) { allocate[i][j] = scanner.nextInt(); } } System.out.println("请输入系统可用的各类资源:"); for (int i = 0; i < resourceCount; i++) { available[i] = scanner.nextInt(); } } public void run() { int processCount = need.length; int resourceCount = available.length; int[] work = new int[resourceCount]; System.arraycopy(available, 0, work, 0, resourceCount); boolean[] finish = new boolean[processCount]; for (int i = 0; i < processCount; i++) { finish[i] = false; } int count = 0; while (count < processCount) { boolean found = false; for (int i = 0; i < processCount; i++) { if (!finish[i]) { boolean enough = true; for (int j = 0; j < resourceCount; j++) { if (need[i][j] > work[j]) { enough = false; break; } } if (enough) { safeSequence[count] = i; count++; finish[i] = true; found = true; for (int j = 0; j < resourceCount; j++) { work[j] += allocate[i][j]; } } } } if (!found) { System.out.println("系统处于不安全状态,无法分配资源!"); return; } } System.out.println("安全序列:"); for (int i = 0; i < processCount; i++) { System.out.print("P" + safeSequence[i]); if (i != processCount - 1) { System.out.print(" -> "); } } System.out.println(); } public static void main(String[] args) { BankerAlgorithm bankerAlgorithm = new BankerAlgorithm(); bankerAlgorithm.init(); bankerAlgorithm.run(); } } ``` 在这个示例代码中,我们通过输入进程数量、资源种类数量、每个进程需要的各类资源、每个进程已分配的各类资源、系统可用的各类资源来初始化我们的银行家算法。接着,我们通过遍历所有进程来找到一个安全的序列。如果无法找到一个安全的序列,则说明当前系统处于不安全状态,无法分配资源。如果找到了一个安全的序列,则输出这个序列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值