Czy karliny Kotlin dają jakieś gwarancje „zdarzy się przed”?
Na przykład, czy w tym przypadku istnieje gwarancja „dzieje się przed” między zapisem mutableVar
a późniejszym odczytem (potencjalnie) innego wątku:
suspend fun doSomething() {
var mutableVar = 0
withContext(Dispatchers.IO) {
mutableVar = 1
}
System.out.println("value: $mutableVar")
}
Edytować:
Być może dodatkowy przykład lepiej wyjaśni pytanie, ponieważ jest to bardziej Kotlin (z wyjątkiem zmienności). Czy ten kod jest bezpieczny dla wątków:
suspend fun doSomething() {
var data = withContext(Dispatchers.IO) {
Data(1)
}
System.out.println("value: ${data.data}")
}
private data class Data(var data: Int)
withContext
środku, podczas gdy pierwszy przykład tworzy go najpierw, mutuje wewnątrzwithContext
, a następnie czyta późniejwithContext
. Tak więc pierwszy przykład zawiera więcej funkcji bezpieczeństwa wątków.Odpowiedzi:
Napisany kod ma trzy dostępy do stanu współdzielonego:
Trzy dostępy są ściśle uporządkowane kolejno, bez współbieżności między nimi, i można mieć pewność, że infrastruktura Kotlin za dba ustanowienia dzieje, przed krawędzią gdy przekazanie off do
IO
puli wątków i powrotem do wywołującego współprogram.Oto równoważny przykład, który może być bardziej przekonujący:
Ponieważ
delay
jest to funkcja zawieszalna i ponieważ używamy programuDefault
rozsyłającego, który jest wspierany przez pulę wątków, linie 1, 2 i 3 mogą być wykonywane w innym wątku. Dlatego twoje pytanie dotyczące gwarancji przed zdarzeniem dotyczy w równym stopniu tego przykładu. Z drugiej strony w tym przypadku (mam nadzieję) jest całkowicie oczywiste, że zachowanie tego kodu jest zgodne z zasadami sekwencyjnego wykonywania.źródło
executorService.submit()
i jest pewien typowy mechanizm oczekiwania na zakończenie zadania (wykonanieCompletableFuture
czegoś podobnego). Z punktu widzenia Kotlinów nie ma tu żadnej współbieżności.Coroutines in Kotlin naprawdę się dzieje przed gwarancjami.
Zasada jest następująca: wewnątrz coroutine kod przed wywołaniem funkcji zawieszenia występuje przed kodem po wywołaniu zawieszenia.
Powinieneś pomyśleć o coroutines tak, jakby były zwykłymi wątkami:
Źródło: https://proandroiddev.com/what-is-concurrent-access-to-mutable-state-f386e5cb8292
Wracając do przykładu kodu. Wychwytywanie zmiennych w ciałach funkcji lambda nie jest najlepszym pomysłem, szczególnie gdy lambda jest koroutyną. Kod przed lambda nie występuje przed kodem w środku.
Zobacz https://youtrack.jetbrains.com/issue/KT-15514
źródło