焉知愚之乐
saojipo.com

多线程死锁现象的发生原因及案例

死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。

从下图可以看出,两条线程A,B使用了嵌套同步锁

线程1抢占CPU资源执行到A锁对象时CPU资源被线程2抢占CPU资源执行到B锁对象,往下执行的时候发现A锁被其他线程获取,线程2进入等待状态,线程1继续运行,发现B锁已被其他线程获取,此时两条线程陷入死锁状态。

案例代码实现:

创建类LockA,并通过修饰构造方法保证对象的唯一性

public class LockA {
// 用private修饰构造方法,让类禁止创建新对象
private LockA(){}
// 创建最终的静态方法以让外部调用
public static final LockA locka = new LockA();
}

创建类LockB,并通过修饰构造方法保证对象的唯一性

public class LockB {
// 用private修饰构造方法,让类禁止创建新对象
private LockB(){}
// 创建最终的静态方法以让外部调用
public static final LockB lockb = new LockB();
}

创建线程类DeadLock

public class DeadLock implements Runnable {
// 创建计数器让线程程序根据运算结果选择要执行的代码块
private int i = 0;
// 重写run方法
public void run() {
// while 死循环
while (true) {
// 如果i等于偶数则执行if代码块
if (i % 2 == 0) {
// 创建同步锁,传入LockA对象
synchronized (LockA.locka) {
System.out.println("if LockA");
// 创建同步锁,传入LockB对象
synchronized (LockB.lockb) {
System.out.println("if LockB");
}
}
// 否则执行else代码块
} else {
// 创建同步锁,传入LockB对象
synchronized (LockB.lockb) {
System.out.println("else LockB");
// 创建同步锁,传入LockB对象
synchronized (LockA.locka) {
System.out.println("else LockA");
}
}
}
i++;
}
}
}

创建测试类test

public class Test {
public static void main(String[] args) {
DeadLock dl = new DeadLock();
Thread t0 = new Thread(dl);
Thread t1 = new Thread(dl);
t0.start();
t1.start();
}
}

避免死锁:

有很多方针可供我们使用来避免死锁的局面。

  • 只对有请求的进行封锁:你应当只想你要运行的资源获取封锁,比如在上述程序中我在封锁的完全的对象资源。但是如果我们只对它所属领域中的一个感兴趣,那我们应当封锁住那个特殊的领域而并非完全的对象。
  • 避免无限期的等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。
  • 避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。例如,这里是另一个运行中没有嵌套封锁的run()方法,而且程序运行没有死锁局面,运行得很成功。
    public class DeadLock implements Runnable {
     // 创建计数器让线程程序根据运算结果选择要执行的代码块
     private int i = 0;
     // 重写run方法
     public void run() {
     // while 死循环
     while (true) {
     // 如果i等于偶数则执行if代码块
     if (i % 2 == 0) {
     // 创建同步锁,传入LockA对象
     synchronized (LockA.locka) {
     System.out.println("if LockA");
    
    }
     // 创建同步锁,传入LockB对象
     synchronized (LockB.lockb) {
     System.out.println("if LockB");
     }
     // 否则执行else代码块
     } else {
     // 创建同步锁,传入LockB对象
     synchronized (LockB.lockb) {
     System.out.println("else LockB");
     }
     // 创建同步锁,传入LockB对象
     synchronized (LockA.locka) {
     System.out.println("else LockA");
     }
     }
     i++;
     }
     }
    }
赞(0)

评论 抢沙发

评论前必须登录!