#java #synchronization
Вопрос:
У меня есть следующий код, в котором несколько потоков вызывают один и тот же метод экземпляра, защищенный статическим объектом
package com.data;
class TestThread {
private final static Object object = new Object();
public void myWaitMethod() {
synchronized (object) {
System.out.println("Before a " Thread.currentThread().getId());
try {
object.wait();
} catch (Exception ignore) {
System.out.println(Thread.currentThread().getId());
}
System.out.println("After a " Thread.currentThread().getId());
}
}
public void myNotifyMethod() {
synchronized (object) {
System.out.println("Before Notify");
object.notifyAll();
System.out.println("After b");
}
}
public static void main(String[] args) throws InterruptedException {
TestThread aa1 = new TestThread();
new Thread(() -> aa1.myWaitMethod()).start();
new Thread(() -> aa1.myWaitMethod()).start();
Thread.sleep(1000);
System.out.println("sleep");
Thread.sleep(1000);
aa1.myNotifyMethod();
}
}
o/p:
Before a 12
Before a 13
sleep
Before Notify
After b
After a 13
After a 12
Я не понимаю, почему «До» дважды печатается, даже если блок синхронизирован.
Ответ №1:
Первая нить получает блокировку, печатает Before A
, вторая нить теперь заблокирована. Затем первый поток вызывает wait
(после вызова wait поток теряет контроль над блокировкой и переходит в состояние ожидания), второй поток получает блокировку, печатает Before A
, а второй поток вызывает wait. (Оба потока находятся в Waiting
состоянии,). Затем основной поток получает блокировку, затем уведомляет об этом для обоих потоков.
На диаграмме, показанной ниже, представлены различные состояния потока в любой момент времени.
Комментарии:
1. Спасибо, я скучаю по документации об ожидании.