Поскольку NewThread1#run()
не синхронизирован, он не будет пытаться установить монитор на цель и поэтому не будет заблокирован, он может вызвать метод на цели, даже если другой поток удерживает его монитор.
Synchronized
может блокировать только другие потоки, только если все потоки конкурируют с одним монитором с синхронизированным разделом.(Неважно, вызовите ли вы test1 или test2, проверка происходит при синхронизации на основе цели).Вы можете сделать синхронизированные методы test1 и test2, после чего они попытаются зарезервировать монитор экземпляра во всех случаях).То же самое верно не только для исключительного выполнения, но и для любых гарантий доступа к памяти (происходит после), которые вы можете захотеть получить из синхронизированного блока.
Кстати, вам не нужны разные классы потоков, если выиспользуйте только один (тот, который синхронизирован), он работает как ожидалось.
Thread t1 = new NewThread2(ob, "t1");
Thread t2 = new NewThread2(ob, "t2");
Однако, если ваша область блокировки узкая, гораздо лучше локализовать блокировку внутри (всех) методов экземпляра целиTest
, потому что тогда вы никогда не сможете вызывать их с отсутствующими синхронизированными (и вы можете переключаться на другие блокирующие примитивы без необходимости знать вызывающую сторону).
void synchronized test1() {
while(1 == 1) {
System.out.println(Thread.currentThread().getName() + " test1!");
}
}
или
void test1() {
synchronized(this) {
while(1 == 1) {
System.out.println(Thread.currentThread().getName() + " test1!");
}
}
}