Bas*_*ass 4 concurrency multithreading kotlin safe-publication kotlin-coroutines
考虑以下 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.")
}
Run Code Online (Sandbox Code Playgroud)
以及使用协程重写的相同示例:
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.")
}
Run Code Online (Sandbox Code Playgroud)
这两个示例在大多数情况下都可以工作,但都被破坏了,因为在字节码级别,boolean从多个线程访问的变量被表示kotlin.jvm.internal.Ref.BooleanRef为非线程安全的。
值得一提的是,Java 编译器需要interrupted这样final,而相同的 Java 代码将根本无法编译。
java.util.concurrent.atomic.AtomicBoolean仅使用标准库(即 w/o或)重写上述代码的规范方法是什么kotlinx.atomicfu.AtomicBoolean?小智 8
\n第一个解决方案是线程安全的数据结构,例如AtmoicBoolean
import java.util.concurrent.atomic.AtomicBoolean\nimport kotlin.concurrent.thread\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\n\nfun main() {\n println("Press <Enter> to terminate.")\n val interrupted = AtomicBoolean()\n val worker = thread {\n while (!interrupted.get()) {\n println("Working...")\n Thread.sleep(1000L)\n }\n }\n\n System.`in`.read()\n println("Terminating...")\n interrupted.set(true)\n worker.join()\n println("Terminated.")\n}\n\n// coroutine way\nfun main_2() = runBlocking {\n println("Press <Enter> to terminate.")\n val interrupted = AtomicBoolean()\n val worker = launch(Dispatchers.IO) {\n while (!interrupted.get()) {\n println("Working...")\n delay(1000L)\n }\n }\n\n System.`in`.read()\n println("Terminating...")\n interrupted.set(true)\n worker.join()\n println("Terminated.")\n}\nRun Code Online (Sandbox Code Playgroud)\n第二种解决方案是互斥
\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.runBlocking\nimport kotlinx.coroutines.sync.Mutex\nimport kotlinx.coroutines.sync.withLock\n\nval mutex = Mutex()\n\nfun main() = runBlocking {\n println("Press <Enter> to terminate.")\n var interrupted = false\n val worker = launch(Dispatchers.IO) {\n while (mutex.withLock { !interrupted }) {\n println("Working...")\n delay(1000L)\n }\n }\n\n System.`in`.read()\n println("Terminating...")\n mutex.withLock { interrupted = true }\n worker.join()\n println("Terminated.")\n}\nRun Code Online (Sandbox Code Playgroud)\n我只是使用两个解决方案来解决这个问题,在这里你可以找到另一个解决方案\n
\n\n如何以最可移植的方式重写上面的代码(第二个片段,使用协程),以便它可以针对 Kotlin/Multiplatform?
\n