为了账号安全,请及时绑定邮箱和手机立即绑定

需要帮助理解 java 中多线程时的内存可见性问题

需要帮助理解 java 中多线程时的内存可见性问题

波斯汪 2023-09-13 10:21:36
我正在实践 Goetze 的 Java 并发性,并且在不使用同步关键字时停留在共享变量的内存可见性部分。代码如下public class NoVisibility {    private static boolean ready;    private static int number;    private static class ReaderThread extends Thread {        public void run() {            while(!ready)                Thread.yield();            System.out.println(number);        }    }    public static void main(String[] args){        new ReaderThread().start();        number=42;        ready=true;    }}作者说这个类可能会永远循环,因为ready的值可能永远不会对读者线程可见。我不明白这个说法。我的看法是,首先主线程启动并将数字和准备设置为 true。但是另一个线程有自己的堆栈以及自己的 number 和 read 值,这些值不与主内存同步,并且这两个线程只有自己的变量副本。现在,读者线程应该永远保持在循环中。我想知道为什么该Thread.yield变量不会屈服于主线程,然后主线程应该刷新到主内存,然后读取线程应该拾取这个新值并终止循环并打印正确的值,因为这也应该是已同步。所以我想我有一些问题。CPU 缓存中的值多久与主内存刷新/同步一次?值可以不与主存同步吗?这也是可能的吗?为什么会出现这种情况呢?当只有一个 cpu 核心和一个 cpu 缓存时,这种内存可见性是否也会发生,还是总是发生?尽管我了解竞争条件和死锁,但我在理解内存可见性问题时遇到了一些困难。这是架构特定的东西吗?
查看完整描述

2 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

CPU 缓存中的值多久与主内存刷新/同步一次?

不明确的。当 JLS 中指定的可见性保证表明需要发生缓存刷新时,就会发生缓存刷新。

值可以不与主存同步吗?这也是可能的吗?

是的。

为什么会出现这种情况呢?

一般来说,缓存被刷新是有原因的。发生之前关系指示可能需要缓存刷新的位置。

当只有一个 cpu 核心和一个 cpu 缓存时,这种内存可见性是否也会发生,还是总是发生?

如果只有一个核心,则缓存刷新不是问题1

尽管我了解竞争条件和死锁,但我在理解内存可见性问题时遇到了一些困难。这是架构特定的东西吗?

是和不是。内存可见性可能会根据硬件架构的不同而有所不同但编写代码以提供明确定义的行为的方式是独立于架构的。

如果您确实需要深入了解内存可见性问题,则需要了解内存模型。Goetz 等人的第 16 章中以通俗易懂的方式对其进行了描述,并在 JLS 中进行了详细说明。


我想知道为什么Thread.yield()调用不会屈服于主线程,然后主线程应该刷新到主内存

  1. 可能Thread.yield() 屈服于另一个可运行的线程。然而,当yield()调用时,线程很可能main不再可运行。(或者它可能仍在运行。)

  2. 不会 在主线程和子线程中的任何语句之间yield()创建发生之前。如果没有发生之前关系,运行时就没有义务确保主线程分配的结果对子线程可见。

  3. 虽然Thread.yield() 可能会执行缓存刷新2,但它将刷新子线程的缓存,而不是父线程的缓存。

因此,子线程的循环可能会无限期地继续下去。


1 - 实际上,这可能过于简单化了。例如,在一个具有一个核心和多个具有自己的缓存的超线程的系统中,将需要缓存刷新。

2 - 例如,如果yield() 确实导致上下文切换,则上下文切换通常包括缓存刷新,作为操作系统执行的线程状态保存的一部分。但是,yield()不一定会导致上下文切换。此外,JLS 并没有规定这方面。


查看完整回答
反对 回复 2023-09-13
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

字段可见性意味着线程观察者字段值来自高速缓存,并且可以具有与 CPU 另一个核心中的其他高速缓存不同的状态。JVM 不保证访问共享资源的不同线程的字段可见性,程序员需要使用 synchronized 来防止读取不正确的状态,或使用 volatile 来保证更改被刷新到其他缓存。



查看完整回答
反对 回复 2023-09-13
  • 2 回答
  • 0 关注
  • 77 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信