java 同步线程说明

java synchronized Thread clarification

这个程序的答案在 5 秒后必须是 "Changing done",但我得到 "Changing done" 和 "DONE"。我没有同步的 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;
    }
}

如果您没有正确同步对 done 的访问,这意味着您的代码 可能 失败,即线程 可能 看不到更新值。

这并不意味着除非正确同步,否则该值保证不可见。因此,在许多情况下,对 done 的写入仍然可见(在许多情况下,损坏的代码仍然有效的事实使并发编程变得更加困难)。只是不能保证在所有情况下都有效。

I do not have the getDone method as synchronized. Any ideas what am I doing for the thread to finish processing.

正如您提到的,done 之间没有明确的内存同步,正如您的旋转线程和主线程所见。尽管主线程在退出 synchronized 块时跨越了写入内存屏障,但自旋线程没有明确跨越读取内存屏障。

但是,线程可以通过多种方式查看更新的信息。如果操作系统将线程换出其 运行 处理器,缓存内存可能会丢失,因此当线程换回时,它将从中央内存请求 done 并看到更新。

此外,虽然您的示例代码没有显示,但如果您调用其他 synchronized 方法(例如 System.out.println())或跨越其他内存障碍(访问另一个 volatile 字段),那么这也会导致 done 被更新。