Есть тестовый код. Четыре потока работают с одним объектом. Два синхронизированных метода. Один статический, другой нет.
1. В моем понимании если один поток заходит в синхронизированный метод объекта то, он захватывает его монитор, следовательно другой поток и остальные должны ждать, но я не могу понять почему заходят оба потока.
2. И есть два статических синхронизированных метода, они относятся к классу, с этим вообще получается не ясно, если мы захватываем метод класса то, все объекты класса не могут быть захвачены остальными потоками. Что я не понимаю?
И главный вопрос, почему все четыре потока в данном примере работают одновременно с одним объектом? Когда как минимум двое должны ждать.
public class Test {
static int vClass = 0;
int object = 0;
static synchronized void incrementClass() {
vClass++;
}
synchronized void incrementObject() {
object++;
}
}
class Main {
public static void main(String[] args) throws InterruptedException {
Test test = new Test();
Thread thread1 = new Thread(()-> {
try {
Test.incrementClass();
System.out.println("зашли в поток класса " + Thread.currentThread().getName());
//Имитация работы потока
Thread.sleep(10000);
Test.incrementClass();
System.out.println("вышли из потока класса " + Thread.currentThread().getName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
Thread thread2 = new Thread(()-> {
Test.incrementClass();
System.out.println("зашли в поток класса " + Thread.currentThread().getName());
Test.incrementClass();
Test.incrementClass();
Test.incrementClass();
System.out.println("вышли из потока класса " + Thread.currentThread().getName());
});
Thread thread3 = new Thread(()-> {
try {
test.incrementObject();
System.out.println("зашли в поток объекта " + Thread.currentThread().getName());
//Имитация работы потока
Thread.sleep(10000);
test.incrementObject();
System.out.println("вышли из потока объекта " + Thread.currentThread().getName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
Thread thread4 = new Thread(()-> {
test.incrementObject();
System.out.println("зашли в поток объекта " + Thread.currentThread().getName());
test.incrementObject();
System.out.println("вышли из потока объекта " + Thread.currentThread().getName());
});
thread1.start();
thread2.start();
thread3.start();
thread4.start();
Thread.sleep(500);
System.out.println("Class " + Test.vClass);
System.out.println("Object " + test.object);
Thread.sleep(10500);
System.out.println("Class " + Test.vClass);
System.out.println("Object " + test.object);
}
}
В результате:
зашли в поток объекта Thread-2
зашли в поток объекта Thread-3
зашли в поток класса Thread-0
зашли в поток класса Thread-1
вышли из потока объекта Thread-3
вышли из потока класса Thread-1
Class 5
Object 3
вышли из потока объекта Thread-2
вышли из потока класса Thread-0
Class 6
Object 4