Java中的死锁是指两个或多个线程在等待对方释放资源时无限期地阻塞的状态,而无法继续执行。这种情况出现在多个线程互相持有对方所需要的锁时,彼此都无法继续执行,就会形成死锁。
以下是两个简单的示例:
示例一:
public class DeadlockExample {
private static final String resource1 = "resource1";
private static final String resource2 = "resource2";
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (resource1) {
System.out.println("Thread1: Holding resource 1...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource2) {
System.out.println("Thread1: Holding resource 1 & 2...");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (resource2) {
System.out.println("Thread2: Holding resource 2...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource1) {
System.out.println("Thread2: Holding resource 2 & 1...");
}
}
});
// 开始执行两个线程
thread1.start();
thread2.start();
}
}
在这个示例中,有两个线程分别需要获取资源1和资源2才能继续执行。如果这两个线程在不同的时间点都已经获得了其中一项资源,但是又都需要另一项资源才能继续执行,那么就会陷入死锁状态。我们可以看到,线程1先获取了resource1,然后睡眠一段时间。在这段时间内,线程2获取了resource2,然后也睡眠。当线程1激活后,它需要获取resource2才能继续执行,而线程2已经持有了resource2,所以线程1会一直阻塞,直到线程2释放了resource2。同样的,当线程2激活后,它需要获取resource1才能继续执行,而线程1已经持有了resource1,所以线程2也会一直阻塞,直到线程1释放了resource1。这就是一个死锁。
示例二:
public class DeadlockExample {
private static final Object resource1 = new Object();
private static final Object resource2 = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (resource1) {
System.out.println("Thread1: Holding resource 1...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource2) {
System.out.println("Thread1: Holding resource 1 & 2...");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (resource2) {
System.out.println("Thread2: Holding resource 2...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource1) {
System.out.println("Thread2: Holding resource 2 & 1...");
}
}
});
// 开始执行两个线程
thread1.start();
thread2.start();
}
}
这是一个类似于示例一的代码,不同的是锁的类型不同,一个是Object类型,一个是String类型。这个示例与示例一相似,但是有一个微妙的差别。因为Java中的String是不可变的,所以会被JVM缓存起来。这意味着当两个线程分别需要获取resource1和resource2但是以不同的顺序获取时,JVM可能会认为需要获取的是同一个String对象,因此这个示例也会产生死锁。
为了避免死锁,我们应该遵守以下规则:
- 只在需要的时候获取锁,然后尽快释放它
- 总是按照相同的顺序获取锁
- 避免持有多个锁并等待另一个锁
- 使用同步块而不是同步方法,这样就可以避免在方法内部出现死锁。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的死锁是什么? - Python技术站