Kotlin 同步无法正常工作

Kotlin synchronized doesn't work properly

我正在尝试创建一个简单的程序,它是使用并发的布朗运动模型(杂质在细胞中随机左右移动)。我有杂质和细胞 classes。单元格 class 包含单元格数组,表示此时每个单元格中有多少杂质。每个杂质对象在自己的线程中更改单元格中的单元格数组。我正在启动线程,它们在无限循环中 运行 1 秒。但在此之前和之后,我打印了细胞中杂质的总和,这些值不相等,这意味着我在同步方面做错了。这是代码:

单元格 class:

object Cells {
    var cell = Array(N) { 0 }

    fun addImpurity(impurity: Impurity) {
        cell[impurity.currentCell]++
    }

    @Synchronized
    fun move(impurity: Impurity, direction: Direction) {
            if (direction == Direction.LEFT && impurity.currentCell > 0) {
                cell[impurity.currentCell]--
                cell[impurity.currentCell - 1]++

                impurity.currentCell--
            } else if (direction == Direction.RIGHT && impurity.currentCell < N - 1) {
                cell[impurity.currentCell]--
                cell[impurity.currentCell + 1]++

                impurity.currentCell++
            }
            Unit
    }

    fun printCells() {
        for (c in cell)
            print("$c ")
    }
}

enum class Direction {
    LEFT, RIGHT
}

杂质class:

class Impurity(var currentCell: Int) {
    private lateinit var thread: Thread

    init {
        Cells.addImpurity(this)
    }

    fun startMoving() {
        thread = Thread {
            while (true) {
                if (random() > P)
                    Cells.move(this, Direction.RIGHT)
                else
                    Cells.move(this, Direction.LEFT)
            }
        }

        thread.start()

    }

    fun stopMoving() = thread.interrupt()
}

和主要:

const val N = 10
const val K = 15
const val P = 0.5

fun main(args: Array<String>) {
    val impurities = ArrayList<Impurity>()

    for (i in 1..K)
        impurities.add(Impurity(0))

    println(Cells.cell.sum())

    startMoving(impurities)

    Thread.sleep(1000)

    stopMoving(impurities)

    Cells.printCells()

    println(Cells.cell.sum())
}

private fun startMoving(impurities: ArrayList<Impurity>) {
    for (impurity in impurities)
        impurity.startMoving()
}

private fun stopMoving(impurities: ArrayList<Impurity>) {
    for (impurity in impurities)
        impurity.stopMoving()
}

提前致谢!

我认为最好通过让线程包含它所引用的一些标志来手动向线程发出它应该完成其工作的信号,以便知道何时退出循环。例如:

class Impurity(var currentCell: Int) {
    ...
    private var _continue = true

    fun startMoving() {
        thread = Thread {
            while (_continue) {
        }
    }

    ...

    fun stopMoving() {
        _continue = false
    }
}

此外,作为对 stopMoving 调用的一部分,您可能还想等到实际线程本身死亡。这将确保在您调用 Cells.printCells 之前,所有线程都确实收到了信号并退出了它们的循环。例如,您可以将此方法添加到 Impurity class:

fun waitForEnded() = thread.join()

并且您可以更新主 class 中的 stopMoving 以在向每个线程发出停止信号后调用此方法:

private fun stopMoving(impurities: ArrayList<Impurity>) {
    for (impurity in impurities)
        impurity.stopMoving()
    impurities.forEach(Impurity::waitForEnded)
}