Apakah Kotlin coroutine memberikan jaminan "terjadi sebelum"?
Sebagai contoh, apakah ada jaminan "terjadi sebelum" antara menulis ke mutableVar
dan selanjutnya membaca (berpotensi) utas lain dalam kasus ini:
suspend fun doSomething() {
var mutableVar = 0
withContext(Dispatchers.IO) {
mutableVar = 1
}
System.out.println("value: $mutableVar")
}
Edit:
Mungkin contoh tambahan akan memperjelas pertanyaan lebih baik karena itu lebih Kotlin-ish (kecuali untuk mutabilitas). Apakah kode ini thread-safe:
suspend fun doSomething() {
var data = withContext(Dispatchers.IO) {
Data(1)
}
System.out.println("value: ${data.data}")
}
private data class Data(var data: Int)
withContext
, sedangkan contoh 1 menciptakannya terlebih dahulu, bermutasi di dalamwithContext
, dan kemudian membacanyawithContext
. Jadi contoh pertama menggunakan lebih banyak fitur keamanan benang.Jawaban:
Kode yang Anda tulis memiliki tiga akses ke status bersama:
Ketiga akses tersebut secara ketat dipesan secara berurutan, tanpa ada konkurensi di antara mereka, dan Anda dapat yakin bahwa infrastruktur Kotlin menangani membangun tepi sebelum terjadi ketika menyerahkan ke
IO
kolam utas dan kembali ke coroutine panggilan Anda.Berikut ini contoh yang setara yang mungkin terlihat lebih meyakinkan:
Karena
delay
merupakan fungsi yang dapat ditangguhkan, dan karena kami menggunakanDefault
dispatcher yang didukung oleh kumpulan utas, baris 1, 2 dan 3 masing-masing dapat dijalankan pada utas yang berbeda. Karenanya pertanyaan Anda tentang jaminan sebelum- berlaku berlaku sama untuk contoh ini. Di sisi lain, dalam hal ini (saya harap) benar-benar jelas bahwa perilaku kode ini konsisten dengan prinsip-prinsip eksekusi berurutan.sumber
executorService.submit()
dan ada beberapa mekanisme khas menunggu penyelesaian tugas (menyelesaikanCompletableFuture
atau sesuatu yang serupa). Dari sudut pandang Kotlin coroutines 'tidak ada konkurensi sama sekali di sini.Coroutine di Kotlin memang menyediakan terjadi sebelum jaminan.
Aturannya adalah: di dalam coroutine, kode sebelum panggilan fungsi ditunda terjadi sebelum kode setelah panggilan ditunda.
Anda harus memikirkan coroutine seolah-olah itu adalah utas biasa:
Sumber: https://proandroiddev.com/what-is-concurrent-access-to-mutable-state-f386e5cb8292
Kembali ke contoh kode. Menangkap vars di badan fungsi lambda bukanlah ide terbaik, terutama ketika lambda adalah coroutine. Kode sebelum lambda tidak terjadi sebelum kode di dalam.
Lihat https://youtrack.jetbrains.com/issue/KT-15514
sumber