Java多线程死锁问题详解(wait和notify)
在Java多线程编程中,死锁问题经常出现,而死锁问题的解决方式通常使用wait()和notify()方法,本文将详细介绍Java多线程死锁问题的解决方法。
什么是死锁?
当两个线程都持有对方需要的锁,并且都在等待对方释放锁的时候,就会出现死锁问题。举个例子,线程A持有锁a并等待锁b,线程B持有锁b并等待锁a,这时候两个线程就会互相等待对方释放锁,形成死锁。
为什么会出现死锁?
通常是因为在多线程环境下,由于不同线程的执行顺序和时间是不可预期的,导致某个线程占用了资源但又未能释放,另一个线程又需要依赖这个资源,就会造成死锁问题。
如何解决死锁?
为了避免死锁问题,Java提供了wait()和notify()方法。
wait()方法会释放当前线程占有的锁,并将线程挂起,进入等待状态。notify()方法则会唤醒等待状态的线程,让它重新尝试获取锁,同样也会释放锁。
当一个线程发现它需要的资源被其他线程占用时,它会首先释放已占有的锁,然后调用wait()方法等待通知。当其他线程释放了资源后,会调用notify()方法通知正在等待的线程,让它重新获取锁。
示例一:
public class DeadlockExample {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void firstThread() throws InterruptedException {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
Thread.sleep(10);
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 and lock 2...");
}
}
}
public void secondThread() throws InterruptedException {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2...");
Thread.sleep(10);
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 1 and lock 2...");
}
}
}
public static void main(String[] args) {
DeadlockExample deadlockExample = new DeadlockExample();
Thread t1 = new Thread(() -> {
try {
deadlockExample.firstThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
deadlockExample.secondThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
上述代码会创建两个线程,分别持有两个对象锁lock1和lock2,互相等待对方释放锁,形成死锁。
为了解决死锁问题,我们可以在其中一个线程中加入notify()方法来唤醒等待锁的线程,如下所示:
示例二:
public class DeadlockExample {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void firstThread() throws InterruptedException {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
Thread.sleep(10);
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 and lock 2...");
lock1.notify(); // 唤醒另一个等待的线程
}
}
}
public void secondThread() throws InterruptedException {
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 1...");
Thread.sleep(10);
System.out.println("Thread 2: Waiting for lock 2...");
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 1 and lock 2...");
}
}
}
public static void main(String[] args) {
DeadlockExample deadlockExample = new DeadlockExample();
Thread t1 = new Thread(() -> {
try {
deadlockExample.firstThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
deadlockExample.secondThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
在第一个线程中加入了notify()方法,当第一个线程获取到了lock2锁之后,会唤醒等待的线程,让它重新尝试获取锁,因此可以避免死锁问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程死锁问题详解(wait和notify) - Python技术站