为什么另一个线程在同步部分尚未完成时访问阻塞对象?

Why does another thread get access to blocked object while synchronized section has not completed?

消息 "main Thread" 在消息 "new Thread" 之前通过方法打印,消息 "new Thread" 在包含打印*方法的对象的同步部分中。

    Test test = new Test();
    new Thread(() -> {
        try {
            synchronized (test) {
                Thread.sleep(5000);
                test.printMessage();
            }
        } catch (InterruptedException e) {}
    }).start();
    Thread.sleep(1000);
    test.printAnotherMessage();
}

public void printMessage() {
    System.out.println("new Thread");
}

public void printAnotherMessage() {
    System.out.println("main Thread");
}

}

在此示例中,printAnotherMessage 与休眠 5 秒的同步块之间没有同步,这就是为什么主线程休眠 1 秒然后打印 main Thread 而无需等待的原因。

您可能打算使 printAnotherMessage 成为一个同步方法。 在这种情况下,主线程将等待另一个线程完成在测试对象上同步的块的执行。

test.printAnotherMessage(); 上没有同步,所以如果时机正确,它将首先执行。 4 秒很多,应该足够了。

synchronized (test) {
    test.printAnotherMessage();
}
不过,

Thread.sleep 很少是一个好的选择。更合适的方法是

Test test = new Test();

new Thread(() -> {
    synchronized (test) {
        test.printMessage();
        test.notify();
    }
}).start();

synchronized (test) {
    test.wait();
    test.printAnotherMessage();
}

我在这里玩一个危险的游戏,因为我假设主线程将进入同步块并执行 wait() before 另一个线程被创建并进入它的同步块。从 creating a thread will take some time 开始就合理了。

Test test = new Test();
new Thread(() -> {
    try {
        // a lot of time to let the main thread execute wait()
        Thread.sleep(500); 

        synchronized (test) {
            test.printMessage();
            test.notify();
        }
    } catch (InterruptedException e) {}
}).start();

synchronized (test) {
    test.wait();
    test.printAnotherMessage();
}