print() 使线程本地缓存无效?

问题描述 投票:0回答:1

在 Java/Kotlin 或任何 JVM 语言中,每个线程都有一个“本地内存”AKA。 “缓存”。当线程想要将变量写入内存时,它首先更新自己缓存中的值,然后将修改同步到主内存中,该内存在线程之间共享。

以下演示说明了发生线程未实现更改的用例:

class VolatileExample3 {

    var flag = false

    var a = 0

    fun write() {
        a = 1
        Thread.sleep(10)
        flag = true
    }

    companion object {
        @JvmStatic
        fun test() {
            val example = VolatileExample3()
            val th = Thread {
                example.write()
            }
            th.start()
            while (!example.flag) {}
            println("a = ${example.a}")
        }
    }
}

线程th调用函数

write()
,首先更新
a
的值,然后休眠10ms作为模拟IO操作,最后将flag设置为true表示“写入”已经完成。

在主线程中,当

flag
为true时,它总是查询flag的值并跳过while循环,这应该是
write()
结束的时间。

我们希望输出为“a = 1”,这就是写入后的正确答案。

但是,因为“本地内存/缓存”的存在,主线程会像卡住一样在

while
中循环。

Main thread won't read Main Memory

write()
的内容运行之前,主线程首先读取
flag
并得到 false,除非我们明确告诉它,否则它不会获取主内存中的值。

问题的答案很明显:将

@Volatile
添加到
flag
,其中
READ
操作将使其本地内存在真正的
LOAD VALUE
之前无效。

但是我找到了这个问题的另一种解决方案:

while (!example.flag) {
    print("")
}

无需

@Volatile
即可工作!我想知道
flush cache
内部的
print()
操作是否会使主线程的本地内存/缓存无效。如果有的话,机制是什么?

我还发现将

th.join()
放在 while 循环之前也有效。这些方法本质上是相同的吗?这意味着一个线程的终止会被所有其他线程注意到,从而导致本地内存失效?

java kotlin concurrency jvm volatile
1个回答
0
投票

如果我将 th.join() 添加到 while 循环中,也会导致主线程缓存失效。为什么会出现这种情况?

© www.soinside.com 2019 - 2024. All rights reserved.