什么是线程死锁?
死锁是指两个或者两个以上的线程在执行过程中,因为争夺资源而造成的互相等待的现象。如果没有外力作用下,这些线程会一直互相等待而无法继续运行下去。
比如说线程A持有资源1,等待资源2
线程B持有资源2,等待资源1
且双方都不愿意放弃自己所持有的资源
死锁的四个条件:
1.互斥条件:资源只能同时被一个线程占用,如果此时有其他线程想要获取资源,则必须等待,直到占有资源的线程释放该资源
2.请求并持有条件:
指一个线程已经持有了至少一个资源,但是又提出了新的资源请求,而新资源已被其他线程占用,所以当前线程会被阻塞,但是又不释放自己的资源。
3.不可剥夺条件:
指线程获取到资源在自己使用完之前不被其他线程抢占,只有在自己使用完毕之后才由自己释放该资源。
4.环路等待条件:指在发生死锁时 必然存在一个线程-资源的环形链,比如说线程1等待线程2的资源,线程2等待线程1的资源
[Java] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
然后就无法继续往下执行了,进入了死锁状态
如何避免死锁?
只需要破坏掉四个死锁条件中的一个构造死锁的必要条件即可。
但是只有请求并持有条件和环路等待条件是可以被破坏的。
资源的互斥条件和不可剥夺条件无法被破坏。
资源申请的有序性原则
让多个线程都使用相同的顺序去获取资源。
比如说之前的线程1获取资源A再获取资源B,线程2获取资源B再获取资源A,这样有可能会发生死锁
但是改成,线程1先获取资源A,再获取B,线程2也先获取资源A再获取资源B.
这样资源A只能被一个线程获取,只有获取到了资源A的线程才会继续去获取资源B。 从而避免了死锁
同时破坏了环路等待条件和请求并持有条件
获取超时则放弃
破坏了请求并持有条件