0
点赞
收藏
分享

微信扫一扫

07Java多线程-13. 死锁概述以及现象演示

芥子书屋 2022-09-13 阅读 62


死锁概述:

定义

多个线程同时等待其他线程释放锁,导致被无限期阻塞

原因

A线程持有锁1,这时主内存的锁1变量进入锁定状态,其他想获得此变量的的线程必须等待。B线程持有锁2,主内存中的锁2变量进入锁定状态。这时A线程再去获取锁2,B线程再去获取锁1,而此时A、B线程都没有对原先锁变量进行解锁,故A线程等待B线程释放锁2,而B线程等待A线程释放锁1。这时就出现了A、B线程同时被无限期阻塞,故导致死锁

代码实现

public class DeadLock {
protected static String locak1="1";
protected static String locak2="2";


public static void main(String[] args) {
Thread thread1=new Thread(new lock1());
Thread thread2=new Thread(new lock2());
thread1.start();
thread2.start();
}


}

class lock1 implements Runnable{
@Override
public void run() {
synchronized (DeadLock.locak1){
System.out.println("lock1:我获得了第一个?");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (DeadLock.locak2){
System.out.println("lock1:我获得了第二个?");
}
}
}
}

class lock2 implements Runnable{
@Override
public void run() {
synchronized (DeadLock.locak2){
System.out.println("lock2:我获得了第一个?");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (DeadLock.locak1){
System.out.println("lock2:我获得了第二个?");
}
}
}
}

避免方法:

加锁顺序:上述例子出现死锁因为A、B线程加锁的顺序不同,如果按照相同顺序,则可以避免死锁

public static void main(String[] args) {
Thread thread1 = new Thread(new lock1());
Thread thread2 = new Thread(new lock2());
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}

  • 加锁时限:给锁加一个超时时间,若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得 的锁,然后等待一段随机的时间再重试。( 注:这种机制存在一个问题,在Java中不能对synchronized同步块设置超时时间。你需要创建一个自定义锁,或使用Java5中java.util.concurrent包下的工具)
  • 死锁检测:死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。(注: 还是上述例子,线程A持有锁1,请求锁2,线程B持有锁2,请求锁1。这时可以让线程A去检测线程B是否已经请求了线程A当前锁持有的锁,如果线程B的确是在请求,则线程A取消请求,并释放锁1,回退和等待。当然现实可能多条线程交叉,它需要递进地检测。)


举报

相关推荐

0 条评论