假设在Kotlin中存在一种用于标记序列和混合命令性代码的方法,作为sequence
函数的参数的lambda中的所需代码是否必须是线程安全的?
例如,以下内容是否安全:
var x: Int = 5
fun someSequence(): Sequence<Int> = sequence {
while (true) {
x++
yield(x)
}
}
fun main(args: Array<String>) {
val seq = someSequence()
seq.take(200).forEach(::println)
}
因为构造序列时没有固有的并行性可利用,所以我不希望操作顺序出现问题。但是,鉴于
sequence
是在协程的帮助下实现的:public fun <T> sequence(@BuilderInference block: suspend SequenceScope<T>.() -> Unit): Sequence<T> = Sequence { iterator(block) }
public fun <T> iterator(@BuilderInference block: suspend SequenceScope<T>.() -> Unit): Iterator<T> {
val iterator = SequenceBuilderIterator<T>()
iterator.nextStep = block.createCoroutineUnintercepted(receiver = iterator, completion = iterator)
return iterator
}
和协程通常不固定在特定线程上,我担心缓存读取。我想象两个替代方案:
sequence
函数要特别小心,以使生成下一个元素的lambda始终在同一线程中执行。协程/暂挂函数是一个实现细节,可将控制流临时转移到序列的使用者。这是@RestrictSuspension
的意思吗? (来自Is this implementation of takeWhileInclusive safe?)sequence
的lambda必须是线程安全的。为什么documentation如此默认? tutorials也仅涵盖非常简单的用例。 请详细说明哪种情况以及原因。
最佳答案
序列的协程在调用线程上执行,因此所有线程安全问题均由调用者负责。
通常,如果将序列传递给其他线程,以便协程每次都在另一个线程上恢复,则您需要确保的是从挂起到恢复之间建立了事前-事前关系,从而提供了总体效果协程已在单个线程上按顺序执行。
关于kotlin - Kotlin的SequenceBuilder的线程安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55394552/