我一直在尝试 Kotlin 同步,但我从文档中不了解锁定机制如何在公共(public)资源上的线程同步上起作用,因此试图编写这段代码,这进一步使我的理解复杂化。
fun main() {
val myList = mutableListOf(1)
thread {
myList.forEach {
while (true) {
println("T1 : $it")
}
}
}
thread {
synchronized(myList) {
while (true) {
myList[0] = 9999
println("**********\n**********\n**********\n")
}
}
}
}
myList
是有问题的公共(public)资源。第一个线程是一个简单的读取操作,我打算将资源保持在读取模式下使用。第二个是另一个请求锁以修改公共(public)资源的线程。
虽然第一个线程不包含任何同步,但我希望它能够在内部处理这个问题,以便一段时间像
map
这样的函数或 forEach
正在处理资源,另一个线程不应该能够锁定它,否则被迭代的元素可能会在 map
/forEach
正在进行中(即使该操作可能会暂停一段时间,而另一个线程对其进行了锁定)。相反,我看到的输出显示两个线程都在并行执行。它们都分别打印列表中的第一个元素和星星。但是在第二个线程中,即使正在打印星星,
myList[0]
永远不会设置为 9999,因为第一个线程继续打印 1。
最佳答案
第二个线程没有改变第一个列表元素的值,如 ==
意味着比较,而不是分配。您需要使用 =
tio 更改值,例如myList[0] = 9999
.但是,在您的代码中,不能保证第二个线程的更改将在第一个线程中可见,因为线程一个未在 myList
上同步.
如果您的目标是 JVM,您应该阅读有关 JVM 内存模型的信息,例如什么是 @Volatile
.您当前的方法不能保证第一个线程会看到第二个线程的更改。您可以将代码简化为 splinter 例子:
var counter = 1
fun main() {
thread {
while (counter++ < 1000) {
println("T1: $counter")
}
}
thread {
while (counter++ < 1000) {
println("T2: $counter")
}
}
}
可以打印奇怪的结果,例如:
T2: 999
T1: 983
T2: 1000
这可以通过几种方式解决,例如通过使用同步。
关于java - Kotlin 中的线程同步是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61828169/