gpt4 book ai didi

multithreading - Kotlin 协程多线程调度器和局部变量的线程安全

转载 作者:行者123 更新时间:2023-12-04 13:24:39 26 4
gpt4 key购买 nike

让我们考虑这个带有协程的简单代码

import kotlinx.coroutines.*
import java.util.concurrent.Executors

fun main() {
runBlocking {
launch (Executors.newFixedThreadPool(10).asCoroutineDispatcher()) {
var x = 0
val threads = mutableSetOf<Thread>()
for (i in 0 until 100000) {
x++
threads.add(Thread.currentThread())
yield()
}
println("Result: $x")
println("Threads: $threads")
}
}
}
据我所知,这是相当合法的协程代码,它实际上产生了预期的结果:
Result: 100000
Threads: [Thread[pool-1-thread-1,5,main], Thread[pool-1-thread-2,5,main], Thread[pool-1-thread-3,5,main], Thread[pool-1-thread-4,5,main], Thread[pool-1-thread-5,5,main], Thread[pool-1-thread-6,5,main], Thread[pool-1-thread-7,5,main], Thread[pool-1-thread-8,5,main], Thread[pool-1-thread-9,5,main], Thread[pool-1-thread-10,5,main]]
问题是什么使局部变量的这些修改成为线程安全的(或者是线程安全的?)。我知道这个循环实际上是按顺序执行的,但它可以在每次迭代时更改正在运行的线程。在第一次迭代中从线程完成的更改仍然应该对在第二次迭代中拾取此循环的线程可见。哪个代码可以保证这种可见性?我试图将此代码反编译为 Java 并使用调试器挖掘协程实现,但没有找到线索。

最佳答案

您的问题完全类似于操作系统可以在线程执行过程中的任何时候挂起线程并将其重新调度到另一个 CPU 内核的认识。这不是因为所讨论的代码是“多核安全的”,而是因为它保证了单个线程根据其程序顺序语义进行行为的环境。
Kotlin 的协程执行环境同样保证了顺序代码的安全性。您应该根据此保证进行编程,而不必担心它是如何维护的。
如果您出于好奇而想深入了解“如何”的细节,那么答案将变成“视情况而定”。每个协程调度器都可以选择自己的机制来实现它。
作为一个有启发性的例子,我们可以关注您在发布的代码中使用的特定调度程序:JDK 的 fixedThreadPoolExecutor .你可以向这个执行器提交任意任务,它会在单个(任意)线程上执行每个任务,但是一起提交的许多任务将在不同的线程上并行执行。
此外,执行器服务提供了导致 executor.execute(task) 的代码的保证。在任务中的代码之前发生,任务中的代码在另一个线程观察其完成之前发生( future.get()future.isCompleted() ,从关联的 CompletionService 获取事件)。
Kotlin 的协程调度器通过依赖执行器服务的这些原语来驱动协程通过其暂停和恢复的生命周期,从而获得整个协程的“顺序执行”保证。每当协程挂起时,提交给执行器的单个任务就会结束​​,当协程准备好恢复时(当用户代码调用 continuation.resume(result) 时),调度程序会提交一个新任务。

关于multithreading - Kotlin 协程多线程调度器和局部变量的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69291492/

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