死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。
从下图可以看出,两条线程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++; } } }
评论前必须登录!
注册