协程线程中使用的Kotlin通道是否安全/同步/保持事前关系?

时间:2019-02-04 16:38:33

标签: kotlin kotlinx.coroutines

Kotlin通道中可用的功能线程安全吗?例如

val channel = Channel<Boolean>()
val job1 = GlobalScope.launch {
    channel.send(true)
}
val job2 = GlobalScope.launch {
    val x = channel.poll()
}

如果上述代码job1是在机器执行job2之前在不同线程上由机器实时执行的,则可以确保x被设置为{{ 1}}?还是可能用true设置了它(因为未更新CPU缓存)?

2 个答案:

答案 0 :(得分:0)

Channel类kotlinx.coroutines库是线程安全的。它旨在支持多个线程。

GlobalScope.launch不一定意味着协程将在新线程中执行

答案 1 :(得分:0)

  

如果上述代码job1是在机器执行job2之前在不同线程上由机器实时执行的,则可以确保x被设置为{{ 1}}?还是可能用true设置了它(因为未更新CPU缓存)?

Java内存模型没有时间的概念,它不能仅仅基于一行比另一行早执行的事实来保证任何事情。您甚至无法确定在CPU上执行动作的时间。

在您发布的代码中,有两个同时执行的协程。 当且仅当 null获得非空值时,才有一个先发边从channel.poll()send() 。如果它得到一个空值,则没有 happens-before 边。

比方说,您确定了两个协程中的挂钟时间,如下所示:

poll()

var sendTime: Long = 0 var receiveTime: Long = 0 suspend fun main() { val channel = Channel<Boolean>(UNLIMITED) val job1 = GlobalScope.launch { channel.send(true) sendTime = System.nanoTime() } val job2 = GlobalScope.launch { receiveTime = System.nanoTime() val x = channel.poll() println(x) } job1.join() job2.join() println("${receiveTime - sendTime}") } 大于receiveTime的事实不会引起先发生关系,并且不会强制sendTime观察发送的项目。调用channel.poll()不是同步操作。

请注意,这些事实与Kotlin或协程无关,这就是Java内存模型的工作方式。如果研究C ++内存模型,您会发现它的工作方式相同。