注册
登录
java
Thread.yield 是否保证将读取/写入刷新到内存?
返回
Thread.yield 是否保证将读取/写入刷新到内存?
作者:
糖果
发布时间:
2025-04-03 01:24:38 (5天前)
让我们保存我有这段代码,它展示了一个线程的陈旧缓存读取,这阻止了它退出它的 while 循环。 class MyRunnable implements Runnable { boolean keepGoing = true; // volatile fixes visibility @Override public void run() { while ( keepGoing ) { // synchronized (this) { } // fixes visibility // Thread.yield(); // fixes visibility System.out.println(); // fixes visibility } } } class Example { public static void main(String[] args) throws InterruptedException, ExecutionException { MyRunnable myRunnable = new MyRunnable(); new Thread(myRunnable).start(); Thread.sleep(100); myRunnable.keepGoing = false; } } 我相信 Java 内存模型保证对 volatile 变量的所有写入与来自任何线程的所有后续读取同步,从而解决了问题。 如果我的理解是正确的,同步块生成的代码也会清除所有挂起的读取和写入,这是一种“内存屏障”并解决了问题。 从实践中我已经看到插入yield和println也会使变量更改对线程可见并且它正确退出。我的问题是: yield/println/io 是否作为 JMM 以某种方式保证的内存屏障,还是无法保证工作的幸运副作用?
收藏
举报
2 条回复
1#
回复此人
糖果
|
2021-09-14 15-29
不。JLS 或方法的 javadoc都不能保证。 在当前的实现,也有在实践中 记忆障碍中yield()和println。(如果您要深入研究实现代码,您应该能够弄清楚它们是如何产生的以及它们的用途是什么。) 但是,不能保证所有平台上Java 1 的所有实现都存在这些内存障碍。该规范没有指定的之前发生存在关系,因此他们不需要2个被插入内存屏障。 假设: 假设这Thread.yield()是作为no-op 实现的。(以同样的方式System.gc()可以是无操作。) 假设输出流堆栈以一种不再需要在引擎盖下同步的方式进行了优化。例如,假设JVM可以推断出特定的输出流是线程限制的,并且在写入其缓冲区时不需要内存屏障。 现在我个人认为这些变化不太可能发生。(而且它们甚至可能不可行。)但如果它们确实发生了,目前依赖于这些偶然内存屏障的相当多的“损坏”应用程序很可能会停止工作。 关键是:如果您想要保证,请依赖规范所说的内容。规范是唯一真正的保证……如果您的代码需要可移植。
编辑
登录
后才能参与评论