死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
首先我们来看下面一段死锁代码
1 package com.company; 2 3 import static java.lang.Thread.sleep; 4 5 public class Main{ 6 private static Integer a = new Integer(0); 7 private static Integer b = new Integer(0); 8 9 public static void main(String...args) { 10 Thread thread1 = new Thread(new Runnable() { 11 @Override 12 public void run() { 13 synchronized (a) { 14 try { 15 System.out.println("thread1 get a"); 16 sleep(1000); // 为防止该线程同时获得a和b两个对象的锁 17 synchronized (b) { 18 System.out.println("thread1 get a and b"); 19 } 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 } 24 } 25 }); 26 27 Thread thread2 = new Thread(new Runnable() { 28 @Override 29 public void run() { 30 synchronized (b) { 31 System.out.println("thread2 get b"); 32 synchronized (a) { 33 System.out.println("thread2 get a and b"); 34 } 35 } 36 } 37 }); 38 thread1.start(); 39 thread2.start(); 40 } 41 }
// output:
thread1 get a
thread2 get b
上面代码运行将会产生死锁,因为thread1在获取a的锁后会尝试获取b的锁,但是因为此时thread2保持着b的锁且thread1保持着thread2所需要的a,因此两个线程陷入僵持状态,产生死锁.
- 解决死锁的办法:
- 避免一个线程同时获取多个锁。
- 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
- 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
- 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。
- 避免一个线程同时获取多个锁。