Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么在同步部分尚未完成时,另一个线程可以访问被阻止的对象?_Java_Multithreading_Synchronized - Fatal编程技术网

Java 为什么在同步部分尚未完成时,另一个线程可以访问被阻止的对象?

Java 为什么在同步部分尚未完成时,另一个线程可以访问被阻止的对象?,java,multithreading,synchronized,Java,Multithreading,Synchronized,消息“main Thread”在消息“new Thread”之前打印,尽管带有消息“new Thread”的方法在包含print*方法的对象的同步部分中 Test test = new Test(); new Thread(() -> { try { synchronized (test) { Thread.sleep(5000); test.printMessage()

消息“main Thread”在消息“new Thread”之前打印,尽管带有消息“new Thread”的方法在包含print*方法的对象的同步部分中

    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()上没有同步
synchronized (test) {
    test.printAnotherMessage();
}
然而,睡眠很少是一个好的选择。更合适的方法是

Test test = new Test();

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

synchronized (test) {
    test.wait();
    test.printAnotherMessage();
}
我在这里玩一个危险的游戏,因为我假设主线程将进入同步块并在创建另一个线程并进入其同步块之前执行
wait()
。这是合理的


只有实例上的显式同步(synchonized方法或synchonized语句)使线程需要该对象上的监视器来执行同步代码。另一个线程不会进入任何
同步的
块。我认为“synchronized(object)”会阻止对该对象的任何成员的访问,无论是同步的还是非同步的not@JaraG,你和许多其他初学者。但它不是这样做的。它只防止其他线程同时在同一对象上同步。(IMO:这只是几个Java特性中的一个,这些特性的用途或意义对于专家来说是显而易见的,但是它们的命名或设计方式让初学者感到困惑。)
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();
}