Consider the following Kotlin code:
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.")
}
as well the same example rewritten using coroutines:
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.")
}
Both examples will work in most cases, and yet both are broken, because, at the bytecode level, a boolean variable accessed from more than a single thread is represented as a kotlin.jvm.internal.Ref.BooleanRef which is not thread-safe.
It's worth mentioning that a Java compiler will require interrupted to be final and the identical Java code will simply fail to compile.
Questions
- What is the canonical way to rewrite the above code using just the standard library (i. e. w/o
java.util.concurrent.atomic.AtomicBooleanorkotlinx.atomicfu.AtomicBoolean)? - How can the above code (the 2nd fragment which uses coroutines) be rewritten in the most portable way, so that it can target Kotlin/Multiplatform?
Based on Kotlin documentation
The first solution is a thread-safe data structure like
AtmoicBooleanSecond solution is Mutual exclusion
I am just using two solutions for this problem in here you can find another solution
I don't have much experience in kotlin-multiplatform, but you can't use `Dispacher.IO` in Kotlin multiplatform because it's bound to the JVM, so if you’re using Kotlin/JavaScript or Kotlin/Native projects, you won’t be able to use it.