As corotinas da Kotlin fornecem alguma garantia "acontece antes"?
Por exemplo, existe uma garantia "acontece antes" entre a gravação mutableVar
e a leitura subsequente (potencialmente) em outro encadeamento neste caso:
suspend fun doSomething() {
var mutableVar = 0
withContext(Dispatchers.IO) {
mutableVar = 1
}
System.out.println("value: $mutableVar")
}
Editar:
Talvez um exemplo adicional esclareça melhor a questão, pois é mais Kotlin-ish (exceto pela mutabilidade). Esse código é seguro para threads:
suspend fun doSomething() {
var data = withContext(Dispatchers.IO) {
Data(1)
}
System.out.println("value: ${data.data}")
}
private data class Data(var data: Int)
withContext
, enquanto o primeiro exemplo o cria primeiro, muda dentrowithContext
e depois lêwithContext
. Portanto, o 1º exemplo exercita mais recursos de segurança de threads.Respostas:
O código que você escreveu possui três acessos ao estado compartilhado:
Os três acessos são estritamente ordenados em sequência, sem simultaneidade entre eles, e você pode ter certeza de que a infraestrutura da Kotlin se encarrega de estabelecer um borda de antes do
IO
acontecimento ao passar para o pool de encadeamentos e retornar à sua rotina de chamada.Aqui está um exemplo equivalente que talvez pareça mais convincente:
Uma vez que
delay
é uma função suspensa, e como estamos usando oDefault
distribuidor que é apoiado por um conjunto de encadeamentos, as linhas 1, 2 e 3 podem ser executadas em um encadeamento diferente. Portanto, sua pergunta sobre garantias de acontecer antes se aplica igualmente a este exemplo. Por outro lado, nesse caso, é (espero) completamente óbvio que o comportamento desse código é consistente com os princípios da execução seqüencial.fonte
executorService.submit()
e existe um mecanismo típico de aguardar a conclusão da tarefa (concluir umaCompletableFuture
ou algo semelhante). Do ponto de vista de Kotlin coroutines, não há simultaneidade aqui.As corotinas em Kotlin fornecem acontecem antes das garantias.
A regra é: dentro de uma rotina, o código anterior a uma chamada de função de suspensão acontece antes do código após a chamada de suspensão.
Você deve pensar nas corotinas como se fossem threads regulares:
Fonte: https://proandroiddev.com/what-is-concurrent-access-to-mutable-state-f386e5cb8292
Voltando ao exemplo de código. Capturar vars em corpos de função lambda não é a melhor ideia, especialmente quando lambda é uma corotina. O código anterior a um lambda não acontece antes do código interno.
Consulte https://youtrack.jetbrains.com/issue/KT-15514
fonte