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
被更新。
这个程序的答案在 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
被更新。