Многопоточность в Java: Deadlock
Deadlock (взаимная блокировка) — это состояние, при котором два или более потоков блокируют друг друга, ожидая освобождения ресурсов, занятых друг другом. Это приводит к тому, что ни один из потоков не может продолжать выполнение.
В этом примере возникает deadlock, потому что thread1 захватывает lock1 и ждет lock2, в то время как thread2 захватывает lock2 и ждет lock1. Таким образом, оба потока оказываются в состоянии взаимной блокировки.
Способы предотвращения Deadlock
Иерархия блокировок: Всегда захватывайте ресурсы в определенном порядке.
Тайм-ауты: Используйте методы с тайм-аутами для захвата блокировок, такие как tryLock из ReentrantLock.
Избегайте вложенных блокировок: Старайтесь минимизировать количество вложенных блокировок.
Пример с использованием tryLock
В этом примере tryLock используется для попытки захвата блокировок с тайм-аутом, что предотвращает возникновение deadlock.
#Java #Training #Multithreading #Medium #Deadlock
Deadlock (взаимная блокировка) — это состояние, при котором два или более потоков блокируют друг друга, ожидая освобождения ресурсов, занятых друг другом. Это приводит к тому, что ни один из потоков не может продолжать выполнение.
public class DeadlockExample {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
public void method2() {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 2 & 1...");
}
}
}
public static void main(String[] args) {
DeadlockExample example = new DeadlockExample();
Thread thread1 = new Thread(example::method1);
Thread thread2 = new Thread(example::method2);
thread1.start();
thread2.start();
}
}
В этом примере возникает deadlock, потому что thread1 захватывает lock1 и ждет lock2, в то время как thread2 захватывает lock2 и ждет lock1. Таким образом, оба потока оказываются в состоянии взаимной блокировки.
Способы предотвращения Deadlock
Иерархия блокировок: Всегда захватывайте ресурсы в определенном порядке.
Тайм-ауты: Используйте методы с тайм-аутами для захвата блокировок, такие как tryLock из ReentrantLock.
Избегайте вложенных блокировок: Старайтесь минимизировать количество вложенных блокировок.
Пример с использованием tryLock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;
public class DeadlockAvoidanceExample {
private final Lock lock1 = new ReentrantLock();
private final Lock lock2 = new ReentrantLock();
public void method1() {
try {
if (lock1.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 1: Holding lock 1...");
Thread.sleep(50);
if (lock2.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 1: Holding lock 1 & 2...");
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void method2() {
try {
if (lock2.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 2: Holding lock 2...");
Thread.sleep(50);
if (lock1.tryLock(50, TimeUnit.MILLISECONDS)) {
try {
System.out.println("Thread 2: Holding lock 2 & 1...");
} finally {
lock1.unlock();
}
}
} finally {
lock2.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
DeadlockAvoidanceExample example = new DeadlockAvoidanceExample();
Thread thread1 = new Thread(example::method1);
Thread thread2 = new Thread(example::method2);
thread1.start();
thread2.start();
}
}
В этом примере tryLock используется для попытки захвата блокировок с тайм-аутом, что предотвращает возникновение deadlock.
#Java #Training #Multithreading #Medium #Deadlock