java synchronized线程澄清

时间:2016-10-17 19:08:55

标签: java multithreading java-8 synchronized

这个程序的答案必须在5秒后完成“改变完成”,但我得到“改变完成”和“完成”。我没有getDone方法同步。我有什么想法为线程完成处理。

public class Main {
    private static boolean done = false;
    private static int count;

    public static void main(String[] args)throws InterruptedException {
        new Thread(() -> {
            while (!getDone()) {
                count = count + 1;
            }
            System.out.println("DONE!!!!");
        }).start();
            Thread.sleep(5000);
        System.out.println("Changing done");
        synchronized (Main.class) {
            done = true;
        }
    }

    public static boolean getDone() {
        return done;
    }
}

2 个答案:

答案 0 :(得分:5)

如果您未正确同步done的访问权限,则表示您的代码可能失败,即线程可能看不到更新的值。

这并不意味着除非正确同步,否则保证值不可见。因此,在许多情况下,对done的写入仍然可见(在许多情况下,破坏的代码仍然有效,这使得并发编程变得更加困难)。它无法保证在每种情况下都能正常工作。

答案 1 :(得分:1)

  

我没有将getDone方法同步化。我有什么想法让线程完成处理。

正如您所提到的,在您的旋转线程和主线程看到的done之间没有明确的内存同步。虽然主线程在退出synchronized块时穿过写入内存屏障,但旋转线程没有明确的读取内存屏障。

但是,线程有很多方法可以查看更新的信息。如果操作系统将线程交换出正在运行的处理器,则缓存的内存可能会丢失,因此当线程被交换回来时,它将从中央内存请求done并将看到更新。

此外,虽然您的示例代码没有显示,但是如果您调用其他synchronized方法(例如System.out.println())或跨越其他内存屏障(访问另一个volatile done更新。