【问题标题】:Adding items to MutableList asynchronously in kotlin在 kotlin 中将项目异步添加到 MutableList
【发布时间】:2019-06-27 13:45:37
【问题描述】:

我正在试验 Kotlin 协程。

假设我有一个可变列表:

val list = mutableListOf<String>()

我启动了 50 个这样的 couroutine:

runBlocking {
    for (i in 1..50) {
        launch(Dispatchers.IO) {
            delay(1000)
            list.add(i.toString())
        }
    }
}
list.forEach { println(it) }

显然,尽管有“延迟(1000)”,但这些操作将需要大约一秒钟,因为它们是异步运行的

这些是不会导致问题的简单操作,但是如果我同时编写很多大字符串怎么办,某些操作会失败吗?

如果使用 appendText 函数写入本地文件,会不会因为文件可能被另一个写入操作锁定而导致某些操作失败?

【问题讨论】:

    标签: kotlin kotlin-coroutines


    【解决方案1】:

    这里的问题是 List 实现可能不是线程安全的:如果两个不同的线程尝试同时更新它,它不能保证正确的操作。

    (这种问题是有害的,因为它在大多数情况下都可以正常工作,但在某些时候会失败,通常是在负载过重的时候。)

    不知道有没有高性能线程安全的List实现。

    一种选择是取一个普通的并将其放入线程安全的包装器中;只要您仅通过该包装器访问它,它将强制执行线程安全(通过使用同步来序列化访问,强制调用者阻塞直到轮到他们)。例如:

    val list = java.util.Collections.synchronizedList(mutableListOf<String>())
    

    另一种是使用专用线程安全的List 实现之一,例如CopyOnWriteArrayList。 (或者如果您只需要迭代而不是完整的List 实现,则有ConcurrentLinkedQueue。)

    (对于Maps 更好;JRE 有ConcurrentHashMap,它是线程安全但高性能的,并且大多数方法不会阻塞。)

    (我不知道File.appendText() 是否是线程安全的。我认为操作系统通常在文件级别提供这种安全性,但我不知道这是否适用于此。)

    【讨论】:

    • 这就是我们在这里的目的!这是非常值得关注的。 HashMap 的一个特别讨厌的故障模式是,如果两个线程尝试同时更新它,一个线程可能会进入无限循环并且永远不会返回......(是的,当我应该知道更好的时候,我已经被它咬了!)这个可变状态的某种问题是人们试图避免它的原因之一,例如函数式编程。
    猜你喜欢
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    相关资源
    最近更新 更多