Java教程-Java中的死锁

Java中的死锁
Java中的死锁是多线程的一部分。当一个线程等待另一个线程已经获得的对象锁,并且第二个线程等待一个被第一个线程已经获得的对象锁时,就会发生死锁。由于两个线程都在等待对方释放锁,所以这种情况被称为死锁。
Java中死锁的示例
TestDeadlockExample1.java
public class TestDeadlockExample1 {
public static void main(String[] args) {
final String resource1 = "ratan jaiswal";
final String resource2 = "vimal jaiswal";
// t1 尝试锁定资源 1,然后锁定资源 2
Thread t1 = new Thread() {
public void run() {
synchronized (resource1) {
System.out.println("Thread 1: locked resource 1");
try { Thread.sleep(100);} catch (Exception e) {}
synchronized (resource2) {
System.out.println("Thread 1: locked resource 2");
}
}
}
};
// t2 尝试锁定 resource2 然后 resource1
Thread t2 = new Thread() {
public void run() {
synchronized (resource2) {
System.out.println("Thread 2: locked resource 2");
try { Thread.sleep(100);} catch (Exception e) {}
synchronized (resource1) {
System.out.println("Thread 2: locked resource 1");
}
}
}
};
t1.start();
t2.start();
}
}
输出:
Thread 1: locked resource 1
Thread 2: locked resource 2
更复杂的死锁
死锁可能涉及多于两个线程。原因是很难检测到死锁。以下是一个涉及四个线程的示例:
线程1锁定A,等待B
线程2锁定B,等待C
线程3锁定C,等待D
线程4锁定D,等待A
线程1等待线程2,线程2等待线程3,线程3等待线程4,线程4等待线程1。
如何避免死锁?
解决问题的方法在于解决其根源。在死锁中,访问资源A和B的模式是主要问题。为了解决此问题,我们只需要重新排列代码访问共享资源的语句即可。
DeadlockSolved.java
public class DeadlockSolved {
public static void main(String ar[]) {
DeadlockSolved test = new DeadlockSolved();
final resource1 a = test.new resource1();
final resource2 b = test.new resource2();
//线程 1
Runnable b1 = new Runnable() {
public void run() {
synchronized (b) {
try {
/* 添加延迟以便两个线程都可以开始尝试锁定资源 */
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Thread-1 有 resource1 但也需要 resource2
synchronized (a) {
System.out.println("In block 1");
}
}
}
};
// 线程 2
Runnable b2 = new Runnable() {
public void run() {
synchronized (b) {
// Thread-2 有 resource2 但也需要 resource1
synchronized (a) {
System.out.println("In block 2");
}
}
}
};
new Thread(b1).start();
new Thread(b2).start();
}
// 资源1
private class resource1 {
private int i = 10;
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
// 资源2
private class resource2 {
private int i = 20;
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
}
输出:
In block 1
In block 2
在上面的代码中,DeadlockSolved类解决了死锁的情况。它有助于避免死锁,并在遇到死锁时解决它们。
如何避免Java中的死锁?
死锁无法完全解决。但是我们可以通过遵循下面提到的基本规则来避免死锁:
- 避免嵌套锁:我们必须避免给多个线程提供锁,这是死锁条件的主要原因。通常情况下,当你给多个线程提供锁时,这种情况就会发生。
- 避免不必要的锁:锁应该只给重要的线程。给不必要的线程提供锁会导致死锁条件。
- 使用线程的Join方法:死锁通常发生在一个线程等待另一个线程完成的情况下。在这种情况下,我们可以使用join方法,并设置一个最大时间,表示线程将花费的最长时间。