Как определить, какой поток получает внутреннюю блокировку объекта?
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
В приведенном выше примере объект, b
, синхронизируется. b
завершает вычисление до того, как главный поток выведет свое общее значение. выход:
Waiting for b to complete...
Total is: 4950
Если main
поток получает блокировку b
сначала, потом main
поток выполнит synchronized(b)
блок. Будет b.wait()
приостановить поток b
(нить b
еще не работает)? Если да, как этот код может дать результат?
Если нить b
сначала получает внутреннюю блокировку, каков результат notify()
?
2 ответа
Будет
b.wait()
приостановить поток b(поток b еще не запущен)? Если да, как этот код может дать результат?
Нет, это synchronized(this)
(где this
относится к тому же объекту, что и b
) который заблокирует другой поток. однажды b.wait
вызывается, монитор на объекте, на который ссылается b
освобождается, основной поток переходит в спящий режим, а другой поток получает монитор, вводя synchronized
блок.
Если поток b сначала получает внутреннюю блокировку, каков результат
notify()
?
Нет ожидающих тем b
/this
, так notify
в принципе ничего не сделаю. Когда ваш другой поток освободит монитор, ваш основной поток получит его и вызовет wait
, ожидая вечно, так как больше нечего notify
Это.
Когда вы используете уведомление / ожидание, вы должны сделать это на основе изменения состояния. если вы этого не сделаете, вы откроете для себя ряд вопросов.
Если вы уведомите (), когда нет ожидающего потока, уведомление будет потеряно. Ожидание wait () может подождать вечно.
Если вы ждете (), он может внезапно проснуться, то есть это не значит, что было уведомление.
Решение - либо;
не использовать notify / wait, поскольку 10 лет назад он был в значительной степени заменен библиотеками параллелизма
поток notify () изменяет поле / состояние, а поток wait () проверяет это в цикле.
Как отмечает Джеймс Лардж, wait () не является справедливым в том смысле, что нет гарантии, что первый ожидающий поток будет уведомлен следующим.
Также вы не можете изменить состояние без удержания одной и той же синхронизированной блокировки и ожидать, что она будет постоянно работать правильно.