gpt4 book ai didi

Kotlin - 从两个线程访问集合时如何锁定集合

转载 作者:行者123 更新时间:2023-12-05 00:57:25 26 4
gpt4 key购买 nike

想知道是否有人可以提供帮助,我正在尝试了解在 Kotlin 中使用两个线程访问集合的正确方法。

下面的代码模拟了我在实时系统中遇到的问题。一个线程遍历集合,但另一个线程可以删除该数组中的元素。

我尝试将 @synchronized 添加到集合 getter 中,但这仍然给我一个并发修改异常。

谁能告诉我正确的做法是什么?

class ListTest() {

val myList = mutableListOf<String>()
@Synchronized
get() = field

init {
repeat(10000) {
myList.add("stuff: $it")
}
}
}

fun main() = runBlocking<Unit> {

val listTest = ListTest()

launch(Dispatchers.Default) {
delay(1L)
listTest.myList.remove("stuff: 54")
}

launch {
listTest.myList.forEach { println(it) }
}
}

最佳答案

你只是在同步 getter 和 setter,所以当你开始使用你得到的列表的引用时,它已经被解锁了。

Kotlin 有 Mutex 类可用于对共享可变对象进行锁定操作。 Mutex 比 Java 的 synchronized 更好,因为它挂起而不是阻塞协程线程。

您的示例在现实世界中的设计很糟糕,因为您的类公开了一个可变列表。但是要确保修改列表至少是安全的:

class ListTest() {

private val myListMutex = Mutex()

private val myList = mutableListOf<String>()

init {
repeat(10000) {
myList.add("stuff: $it")
}
}

suspend fun modifyMyList(block: MutableList<String>.() -> Unit) {
myListMutex.withLock { myList.block() }
}
}

fun main() = runBlocking<Unit> {

val listTest = ListTest()

launch(Dispatchers.Default) {
delay(1L)
listTest.modifyMyList { it.remove("stuff: 54") }
}

launch {
listTest.modifyMyList { it.forEach { println(it) } }
}
}

如果你不使用协程,而不是 Mutex(),你可以使用 Any 而不是 withLock 使用 synchronized (myListLock) {} 就像在 Java 中一样,防止同步块(synchronized block)中的代码同时运行。

关于Kotlin - 从两个线程访问集合时如何锁定集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60137697/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com