¿Las corutinas de Kotlin ofrecen garantías de "sucede antes"?
Por ejemplo, ¿existe una garantía de "sucede antes" entre la escritura mutableVar
y la posterior lectura en (potencialmente) otro hilo en este caso:
suspend fun doSomething() {
var mutableVar = 0
withContext(Dispatchers.IO) {
mutableVar = 1
}
System.out.println("value: $mutableVar")
}
Editar:
Tal vez un ejemplo adicional aclare mejor la pregunta porque es más Kotlin-ish (excepto por la mutabilidad). ¿Es este código seguro para subprocesos?
suspend fun doSomething() {
var data = withContext(Dispatchers.IO) {
Data(1)
}
System.out.println("value: ${data.data}")
}
private data class Data(var data: Int)
withContext
, mientras que el primer ejemplo lo crea primero, muta dentrowithContext
y luego leewithContext
. Entonces, el primer ejemplo ejerce más características de seguridad de hilo.Respuestas:
El código que escribió tiene tres accesos al estado compartido:
Los tres accesos están estrictamente ordenados secuencialmente, sin concurrencia entre ellos, y puede estar seguro de que la infraestructura de Kotlin se encarga de establecer un límite antes de
IO
pasar al grupo de subprocesos y volver a su rutina de llamadas.Aquí hay un ejemplo equivalente que quizás parezca más convincente:
Dado que
delay
es una función suspendible, y dado que estamos utilizando elDefault
despachador respaldado por un grupo de subprocesos, las líneas 1, 2 y 3 pueden ejecutarse en un subproceso diferente. Por lo tanto, su pregunta sobre suceder antes garantías de aplica igualmente a este ejemplo. Por otro lado, en este caso es (espero) completamente obvio que el comportamiento de este código es consistente con los principios de ejecución secuencial.fuente
executorService.submit()
y hay algún mecanismo típico de espera a la finalización de la tarea (completar unaCompletableFuture
o algo similar). Desde el punto de vista de las corutinas de Kotlin no hay concurrencia en absoluto aquí.Las corutinas en Kotlin ofrecen antes que las garantías.
La regla es: dentro de una rutina, el código antes de una llamada de función de suspensión ocurre antes del código después de la llamada de suspensión.
Debes pensar en las corutinas como si fueran hilos regulares:
Fuente: https://proandroiddev.com/what-is-concurrent-access-to-mutable-state-f386e5cb8292
Volviendo al ejemplo de código. La captura de vars en cuerpos de funciones lambda no es la mejor idea, especialmente cuando lambda es una rutina. El código anterior a un lambda no ocurre antes del código interno.
Ver https://youtrack.jetbrains.com/issue/KT-15514
fuente