线程死锁以及死锁解决的方法
程序员文章站
2022-04-17 14:05:12
...
线程死锁以及死锁解决的方法
目录
一、什么是死锁
死锁是在两个以及两个以上线程在执行的过程中,由于资源竞争而出现的一种阻塞现象,如果没有外力作用,将会持续下去。
二、死锁产生的条件
- 互斥条件:每个锁资源一次只能有一个线程持有。
- 请求保持:线程拿着锁获取其他锁,并且不释放自己手中的锁。
- 不可剥夺:当一个线程没有自动释放锁之前,不可被动释放锁资源。
- 循环条件:多个线程由于资源竞争,形成的一种闭环。
三、代码演示
1. 死锁产生
public class DeadLockAction {
/**
* 三把锁
*/
private static ReentrantLock lock1 = new ReentrantLock();
private static ReentrantLock lock2 = new ReentrantLock();
private static ReentrantLock lock3 = new ReentrantLock();
public static void main(String[] args) {
//线程1的加锁顺序 lock1 lock2 lock3
Thread thread1 = new Thread(()->{
lock1.lock();
//为了提高死锁产生的次数 让线程睡眠5ms
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock2.lock();lock3.lock();
System.out.println("线程1拿到所有的锁");
lock1.unlock();lock2.unlock();lock3.unlock();
});
//线程2的加锁顺序 lock2 lock3 lock1
Thread thread2 = new Thread(()->{
lock2.lock();
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock3.lock();lock1.lock();
System.out.println("线程2拿到所有的锁");
lock2.unlock();lock3.unlock();lock1.unlock();
});
//线程3的加锁顺序 lock3 lock1 lock2
Thread thread3 = new Thread(()->{
lock3.lock();
try {
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock1.lock();lock2.lock();
System.out.println("线程3拿到所有的锁");
lock3.unlock();lock1.unlock();lock2.unlock();
});
thread1.start();thread2.start();thread3.start();
}
}
2. 调整加锁顺序避免死锁产生
线程加锁的顺序必须按照某一顺序加锁,例如想获取锁3,必须先获得锁2,获取锁2,必须获得锁1,也就是加锁的顺序必须是锁1,锁2,锁3。调整加锁顺序的前提是需要与之需要的锁,但总是不可预知的。
public class DeadLockAction {
/**
* 三把锁
*/
private static ReentrantLock lock1 = new ReentrantLock();
private static ReentrantLock lock2 = new ReentrantLock();
private static ReentrantLock lock3 = new ReentrantLock();
public static void main(String[] args) {
//线程1的加锁顺序 lock1 lock2 lock3
Thread thread1 = new Thread(()->{
lock1.lock();lock2.lock();lock3.lock();
System.out.println("线程1拿到所有的锁");
lock1.unlock();lock2.unlock();lock3.unlock();
});
//线程2的加锁顺序 lock1 lock2 lock3
Thread thread2 = new Thread(()->{
lock1.lock();lock2.lock();lock3.lock();
System.out.println("线程2拿到所有的锁");
lock1.unlock();lock2.unlock();lock3.unlock();
});
//线程3的加锁顺序 lock1 lock2 lock3
Thread thread3 = new Thread(()->{
lock1.lock();lock2.lock();lock3.lock();
System.out.println("线程3拿到所有的锁");
lock1.unlock();lock2.unlock();lock3.unlock();
});
thread1.start();thread2.start();thread3.start();
}
}
3. 加锁时限避免死锁产生
加锁时,这只加锁的时间限制,超过某个时间得不到某个锁,就释放手中的所有的锁,隔段时间再次尝试加锁。
public class DeadLockAction {
/**
* 三把锁
*/
private static ReentrantLock lock1 = new ReentrantLock();
private static ReentrantLock lock2 = new ReentrantLock();
private static ReentrantLock lock3 = new ReentrantLock();
public static void main(String[] args) {
//线程1的加锁顺序 lock1 lock2 lock3
Thread thread1 = new Thread(()->{
try {
while(lock1.tryLock(1, TimeUnit.SECONDS)) {
//让死锁必产生
TimeUnit.MILLISECONDS.sleep(5);
if(lock2.tryLock(1, TimeUnit.SECONDS)){
if(lock3.tryLock(1, TimeUnit.SECONDS)){
System.out.println("线程1拿到所有的锁");
lock1.unlock();
lock2.unlock();
lock3.unlock();
//线程执行完毕退出
break;
}
//释放锁2
if(lock2.isHeldByCurrentThread()){
lock2.unlock();
}
}
//释放锁1
if(lock1.isHeldByCurrentThread()){
lock1.unlock();
}
//等待一段时间
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
//线程2的加锁顺序 lock2 lock3 lock1
Thread thread2 = new Thread(()->{
try {
while(lock2.tryLock(1, TimeUnit.SECONDS)) {
//让死锁必产生
TimeUnit.MILLISECONDS.sleep(5);
if(lock3.tryLock(1, TimeUnit.SECONDS)){
if(lock1.tryLock(1, TimeUnit.SECONDS)){
System.out.println("线程2拿到所有的锁");
lock1.unlock();
lock2.unlock();
lock3.unlock();
//线程执行完毕退出
break;
}
if(lock3.isHeldByCurrentThread()){
lock3.unlock();
}
}
if(lock2.isHeldByCurrentThread()){
lock2.unlock();
}
//等待一段时间
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
//线程3的加锁顺序 lock3 lock1 lock2
Thread thread3 = new Thread(()->{
try {
while(lock3.tryLock(1, TimeUnit.SECONDS)) {
//让死锁必产生
TimeUnit.MILLISECONDS.sleep(5);
if(lock1.tryLock(1, TimeUnit.SECONDS)){
if(lock2.tryLock(1, TimeUnit.SECONDS)){
System.out.println("线程3拿到所有的锁");
lock1.unlock();
lock2.unlock();
lock3.unlock();
//线程执行完毕退出
break;
}
if(lock1.isHeldByCurrentThread()){
lock1.unlock();
}
}
if(lock3.isHeldByCurrentThread()){
lock3.unlock();
}
//等待一段时间
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread1.start();thread2.start();thread3.start();
}
}