搜索
写经验 领红包
 > 美容

线程死锁的四个必要条件(线程死锁和进程死锁区别)

导语:什么是线程死锁?如何避免死锁?看一次就明白

认识线程死锁

线程死锁描述的是这样一种情况:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期的阻塞,因此程序不可能正常终止。

如下图所示,线程A持有资源2,线程B持有资源1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。

下面通过一个例子来说明线程死锁,代码模拟了上面死锁的情况(代码来源于《并发编程之美》);

Output:

线程A通过synchronized(resource1)获得resource1的监视器锁,然后通过Thread.sleep(1000);让线程A休眠1秒,为了是让线程B得到执行然后获取到resource2的监视器锁。线程A和线程B休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。上面的例子产生死锁的4个必要条件。

学过操作系统的朋友都知道产生死锁必须具备以下4个条件:

互斥条件:该资源任意一个时刻只由一个线程占用。请求与保持条件:一个进程因为请求资源而阻塞时,对已获得的资源保存不放。不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强制剥夺,只有之间使用完毕后才会释放资源。循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

如何避免线程死锁?

我上面说了产生死锁的4个必要条件,为了避免死锁,我们只要破坏产生死锁的4个条件中的1个就可以了,我们现在来挨个分析一下:

破坏互斥条件:这个条件我们没有办法破坏,因为我们用锁本来就是想让它们互斥的(临界资源需要互斥访问)。破坏请求与保持条件:一次性申请所有资源。破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源破坏循环等待条件:按某一个顺序来申请资源,释放资源则反序释放。破坏循环等待条件

我们对线程2的代码修改成下面这个就不会产生死锁了。

Output:

我们分析一下上面的代码为什么避免了死锁的发生?

线程1首先获取到resource1的监视器锁,这时候线程2就获取不到了。然后线程1再去获取resource2的监视器锁,可以获取到。然后线程1释放了resource1、resource2的监视器锁的占用,线程2获取到就可以执行了,这样就破坏了破坏循环等待条件,因此就避免了死锁。

本文内容由小岑整理编辑!