Два потока, выполняющие синхронизированный блок одновременно
Ниже приведен код, в котором Thread
входит в синхронизированный блок, ждет 5 секунд и затем выходит. Я начал два экземпляра Thread
одновременно.
Ожидание было одним из потоков будет иметь блокировку синхронизированного объекта, а другая будет ждать. Через 5 секунд, когда владелец замка завершает работу, выполняется поток ожидания.
Но в действительности оба потока одновременно выполняют синхронизированный блок, а также одновременно выходят из него.
Ожидаемый результат:
Thread-X <timeX> received the lock.
Thread-X <timeX+5s> exiting...
Thread-Y <timeY> received the lock.
Thread-Y <timeY+5s> exiting...
Фактический результат:
Thread-X <time> received the lock.
Thread-Y <time> received the lock.
Thread-X <time+5s> exiting...
Thread-Y <time+5s> exiting...
Я что-то упустил?
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test2 {
public static void main(String[] args) {
MyRunnable m = new MyRunnable();
Thread t = new Thread(m);
Thread t1 = new Thread(m);
t.start();
t1.start();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
synchronized (this) {
try {
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = new Date(System.currentTimeMillis());
System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " received the lock.");
wait(5000);
date = new Date(System.currentTimeMillis());
System.out.println(Thread.currentThread().getName() + " " + formatter.format(date) + " exiting...");
} catch(InterruptedException ie) {}
}
}
}
Ответы
Ответ 1
Ответ заключается в java.lang.Object.wait(long), чья документация гласит:
[...] Этот метод заставляет текущий поток (называть его T) помещать себя в набор ожидания для этого объекта, а затем отказываться от любых и всех заявлений о синхронизации на этом объекте. [...]
Ответ 2
использование
Thread.sleep(5000);
JavaDocs для Thread.sleep:
Заставляет текущий исполняемый поток спать (временно прекратить выполнение) за указанное количество миллисекунд, с учетом точности и точности системных таймеров и планировщиков. Нить не теряет права собственности на какие-либо мониторы.
Ответ 3
Следующая цитата из Oracle Tutorials объясняет ситуацию:
Когда wait
вызывается, поток освобождает блокировку и приостанавливает выполнение.
Кроме того, только один поток может выполнять synchronized
блок, защищенный одним и тем же объектом! Ожидание wait
в вашем примере освобождает блокировку, что позволяет другому потоку получить блокировку.