空的问题,添加一些随机打印修复错误

Problem with empty while, adding some random print fixes bug

我试图从使用 GUI 的用户那里获取一些信息,该用户使用 Kotlin(Jvm) 在单独的线程中运行。我这样做的尝试是(最小的工作示例,我无法摆脱 UI

import java.awt.*
import java.lang.Thread.sleep
import javax.swing.*


val board = Board()

fun main() {
    EventQueue.invokeLater {
        ThreadAnimationEx().isVisible = true
    }
    var test: String?=null
    board.instruction = {
        sleep(1000)
        test= "test value"
        println("Done")
    }
    while (test == null) {
        //uncommenting this line makes this work
//        sleep(100)
    }
    println("Finished with $test")
}



class ThreadAnimationEx() : JFrame() {
    init {
        add(board)
    }
}

class Board : JPanel(), Runnable {
    var instruction: (() -> Unit)? = null

    private var animator: Thread? = null

    override fun addNotify() {
        super.addNotify()
        animator = Thread(this)
        animator!!.start()
    }

    public override fun paintComponent(g: Graphics) {
        super.paintComponent(g)
        Toolkit.getDefaultToolkit().sync()
    }

    override fun run() {
        while (true) {
            if (instruction != null) {
                instruction!!.invoke()
                instruction = null
            }
            sleep(10)
        }
    }
}

如果 sleep(100) 没有被注释掉那么程序可以正常工作,打印

Done
Finished with test value

如果没有这样的片段那么我只得到

Done

这是 kotlin 或 jvm 中的一些错误吗?

不,这是您程序中的错误。没有任何迹象表明 test 的值会发生变化,因此 JVM 在执行 [=11] 中的条件测试时完全有权使用缓存在寄存器中的值而不是从内存中获取值=]循环。

您需要在 test 变量上使用 volatile 修饰符或使用专为并发设计的类型,例如 AtomicBoolean.

顺便说一下,调用 sleep 修复它的原因大概是因为发生了一些同步,导致内存屏障,迫使值再次从内存中获取。这类似于为什么打印也可以解决这种并发可见性问题,如 this question and answer.

中探讨的那样