Bieten Kotlin-Coroutinen Garantien für "Vorheriges"?
mutableVar
Gibt es in diesem Fall beispielsweise eine "Vorher-passiert" -Garantie zwischen dem Schreiben in und dem anschließenden Lesen eines (möglicherweise) anderen Threads:
suspend fun doSomething() {
var mutableVar = 0
withContext(Dispatchers.IO) {
mutableVar = 1
}
System.out.println("value: $mutableVar")
}
Bearbeiten:
Vielleicht klärt ein zusätzliches Beispiel die Frage besser, weil es mehr Kotlin-artig ist (mit Ausnahme der Veränderlichkeit). Ist dieser Code threadsicher:
suspend fun doSomething() {
var data = withContext(Dispatchers.IO) {
Data(1)
}
System.out.println("value: ${data.data}")
}
private data class Data(var data: Int)
withContext
, während das erste Beispiel es zuerst erstellt, darin mutiertwithContext
und danach liestwithContext
. Im ersten Beispiel werden also mehr Thread-Sicherheitsfunktionen ausgeführt.Antworten:
Der von Ihnen geschriebene Code hat drei Zugriffe auf den freigegebenen Status:
Die drei Zugriffe sind streng nacheinander angeordnet, ohne dass eine Parallelität zwischen ihnen besteht, und Sie können sicher sein, dass die Infrastruktur von Kotlin dafür sorgt, dass bei der Übergabe an den Thread-Pool und zurück an Ihre aufrufende Coroutine eine Vorab- Kante entsteht
IO
.Hier ist ein gleichwertiges Beispiel, das vielleicht überzeugender aussieht:
Da
delay
es sich um eine suspendierbare Funktion handelt und wir denDefault
Dispatcher verwenden, der von einem Thread-Pool unterstützt wird, können die Zeilen 1, 2 und 3 jeweils in einem anderen Thread ausgeführt werden. Daher gilt Ihre Frage zu Vorabgarantien auch für dieses Beispiel. Andererseits ist es in diesem Fall (ich würde hoffen) völlig offensichtlich, dass das Verhalten dieses Codes mit den Prinzipien der sequentiellen Ausführung übereinstimmt.quelle
executorService.submit()
läuft es darauf hinaus und es gibt einen typischen Mechanismus, um auf den Abschluss der Aufgabe zu warten (Abschluss einerCompletableFuture
oder ähnlicher Aufgaben ). Aus Sicht der Kotlin Coroutines gibt es hier überhaupt keine Parallelität.Coroutinen in Kotlin bieten vor Garantien.
Die Regel lautet: Innerhalb einer Coroutine erfolgt der Code vor einem Suspend-Funktionsaufruf vor dem Code nach dem Suspend-Aufruf.
Sie sollten sich Coroutinen so vorstellen, als wären sie normale Threads:
Quelle: https://proandroiddev.com/what-is-concurrent-access-to-mutable-state-f386e5cb8292
Zurück zum Codebeispiel. Das Erfassen von Vars in Lambda-Funktionskörpern ist nicht die beste Idee, insbesondere wenn Lambda eine Coroutine ist. Der Code vor einem Lambda kommt nicht vor dem Code vor.
Siehe https://youtrack.jetbrains.com/issue/KT-15514
quelle