2 回答
TA贡献1880条经验 获得超4个赞
CPU 缓存中的值多久与主内存刷新/同步一次?
不明确的。当 JLS 中指定的可见性保证表明需要发生缓存刷新时,就会发生缓存刷新。
值可以不与主存同步吗?这也是可能的吗?
是的。
为什么会出现这种情况呢?
一般来说,缓存被刷新是有原因的。发生之前关系指示可能需要缓存刷新的位置。
当只有一个 cpu 核心和一个 cpu 缓存时,这种内存可见性是否也会发生,还是总是发生?
如果只有一个核心,则缓存刷新不是问题1。
尽管我了解竞争条件和死锁,但我在理解内存可见性问题时遇到了一些困难。这是架构特定的东西吗?
是和不是。内存可见性可能会根据硬件架构的不同而有所不同,但编写代码以提供明确定义的行为的方式是独立于架构的。
如果您确实需要深入了解内存可见性问题,则需要了解内存模型。Goetz 等人的第 16 章中以通俗易懂的方式对其进行了描述,并在 JLS 中进行了详细说明。
我想知道为什么
Thread.yield()
调用不会屈服于主线程,然后主线程应该刷新到主内存
可能
Thread.yield()
会屈服于另一个可运行的线程。然而,当yield()
调用时,线程很可能main
不再可运行。(或者它可能仍在运行。)不会 在主线程和子线程中的任何语句之间
yield()
创建发生之前。如果没有发生之前关系,运行时就没有义务确保主线程分配的结果对子线程可见。虽然
Thread.yield()
可能会执行缓存刷新2,但它将刷新子线程的缓存,而不是父线程的缓存。
因此,子线程的循环可能会无限期地继续下去。
1 - 实际上,这可能过于简单化了。例如,在一个具有一个核心和多个具有自己的缓存的超线程的系统中,将需要缓存刷新。
2 - 例如,如果yield()
确实导致上下文切换,则上下文切换通常包括缓存刷新,作为操作系统执行的线程状态保存的一部分。但是,yield()
不一定会导致上下文切换。此外,JLS 并没有规定这方面。
TA贡献1824条经验 获得超6个赞
字段可见性意味着线程观察者字段值来自高速缓存,并且可以具有与 CPU 另一个核心中的其他高速缓存不同的状态。JVM 不保证访问共享资源的不同线程的字段可见性,程序员需要使用 synchronized 来防止读取不正确的状态,或使用 volatile 来保证更改被刷新到其他缓存。
添加回答
举报