gpt4 book ai didi

multithreading - 从多个线程线程安全地访问 Kotlin var

转载 作者:行者123 更新时间:2023-12-02 13:17:43 27 4
gpt4 key购买 nike

考虑以下 Kotlin 代码:

import kotlin.concurrent.thread

fun main() {
println("Press <Enter> to terminate.")

var interrupted = false

val worker = thread {
while (!interrupted) {
println("Working...")
Thread.sleep(1000L)
}
}

System.`in`.read()

println("Terminating...")
interrupted = true

worker.join()

println("Terminated.")
}

以及使用协程重写的相同示例:

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
println("Press <Enter> to terminate.")

var interrupted = false

val worker = launch(Dispatchers.IO) {
while (!interrupted) {
println("Working...")
delay(1000L)
}
}

System.`in`.read()

println("Terminating...")
interrupted = true

worker.join()

println("Terminated.")
}

这两个示例在大多数情况下都可以工作,但都被破坏了,因为在字节码级别,从多个线程访问的 boolean 变量表示为 kotlin。 jvm.internal.Ref.BooleanRef 不是线程安全的。

值得一提的是,Java 编译器将要求 interruptedfinal,而相同的 Java 代码将无法编译。

问题

  1. 仅使用标准库(即不使用 java.util.concurrent.atomic.AtomicBooleankotlinx.atomicfu.AtomicBoolean)重写上述代码的规范方法是什么?
  2. 如何以最可移植的方式重写上面的代码(使用协程的第二个片段),以便它可以针对 Kotlin/Multiplatform

最佳答案

基于 Kotlin documentation

第一个解决方案是线程安全的数据结构,如AtmoicBoolean

import java.util.concurrent.atomic.AtomicBoolean
import kotlin.concurrent.thread
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() {
println("Press <Enter> to terminate.")
val interrupted = AtomicBoolean()
val worker = thread {
while (!interrupted.get()) {
println("Working...")
Thread.sleep(1000L)
}
}

System.`in`.read()
println("Terminating...")
interrupted.set(true)
worker.join()
println("Terminated.")
}

// coroutine way
fun main_2() = runBlocking {
println("Press <Enter> to terminate.")
val interrupted = AtomicBoolean()
val worker = launch(Dispatchers.IO) {
while (!interrupted.get()) {
println("Working...")
delay(1000L)
}
}

System.`in`.read()
println("Terminating...")
interrupted.set(true)
worker.join()
println("Terminated.")
}

第二种解决方案是 Mutual exclusion

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

val mutex = Mutex()

fun main() = runBlocking {
println("Press <Enter> to terminate.")
var interrupted = false
val worker = launch(Dispatchers.IO) {
while (mutex.withLock { !interrupted }) {
println("Working...")
delay(1000L)
}
}

System.`in`.read()
println("Terminating...")
mutex.withLock { interrupted = true }
worker.join()
println("Terminated.")
}

我只是针对这个问题使用了两种解决方案,您可以在这里找到 another solution

How can the above code (the 2nd fragment, which uses coroutines) be rewritten in the most portable way so it can target Kotlin/Multiplatform?


我在 kotlin-multiplatform 方面没有太多经验,但是你不能在 Kotlin multiplatform 中使用 `Dispacher.IO` 因为它绑定(bind)到 JVM,所以如果你使用 Kotlin/JavaScript 或 Kotlin/Native 项目,你将无法使用它。

关于multithreading - 从多个线程线程安全地访问 Kotlin var,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61932947/

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