欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

并发编程之死锁的整理

程序员文章站 2022-04-17 14:44:53
...

死锁一般发生在多线程执行的过程中,两个或者两个以上的线程在执行的时候,因为争夺共享资源而造成的线程间相互等待.

一般,发生死锁时满足四个条件:

1.互斥条件。资源同一时间只能被一个线程所持有,即线程A所持有的资源不能被其他线程持有。

2.持有并等待条件。即线程A所持有资源1,又想申请持有资源2,但是资源2被其他线程所持有,所以线程A就处于等待资源2的同时不会释放资源1.

3.不可剥夺条件。即线程A获取资源1后,在使用完之前不能被其他线程抢占使用,只能自己主动释放。

4.环路等待条件。即发生死锁时,必然出现例如线程A获取了资源1,正在请求资源2;但是资源2已经被线程B所持有,此时正请求资源1,类似此种情况产生的环路请求等待。

那么我们该如何避免死锁呢,我们只需要打破其中的一个条件即可,我们通常将资源的有效获取定位一定顺序即可,即多个方法获取资源的顺序保持一致。伪代码如下:

private static Thread createThreadA() {
    Thread threadB = new Thread(() -> {
        //1 尝试获取资源 A
        synchronized (resourceA) {
            System.out.println(Thread.currentThread() + " got ResourceA");
            //2 执行业务代码
            try {
                //业务代码
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread() + "waiting get ResourceB");
            //3 尝试获取资源 B
            synchronized (resourceB) {
                System.out.println(Thread.currentThread() + "got ResourceB");
            }
        }
    }, "ThreadB");
    return threadB;
}

上面的代码为在方法A中建立线程,先锁定资源即占有资源A,然后在获取资源B,则在其他方法代码逻辑中同样要先获取资源A,再获取资源B即可解决死锁问题。