Middle+
Kaip galima įgyvendinti sinchronizaciją Kotlin naudojant korutinas?
sobes.tech AI
Atsakymas iš AI
Kotlin korutinų sinchronizacija pasiekiama naudojant specialius primitivius ir duomenų struktūras iš kotlinx.coroutines bibliotekos.
Pagrindiniai požiūriai:
-
Mutex
- Užtikrina tarpusavio išimtį kritinėse sekcijose.
- Korutina, bandanti gauti Mutex, blokuojama iki kol jis bus laisvas.
- Turi
lock()irunlock()funkcijas, taip pat labiau idiomatiniuswithLock.
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.* val mutex = Mutex() var counter = 0 suspend fun increment() { mutex.withLock { counter++ } } suspend fun main() = coroutineScope { repeat(10_000) { launch { increment() } } println(counter) // Tikimės 10000 } -
Semaphore
- Ribojamas vienu metu veikiančių korutinų skaičius, kurie gali vienu metu pasiekti išteklių arba vykdyti tam tikrą bloką.
- Valdo leidimų pulą.
- Turi
acquire()irrelease()funkcijas, taip patwithPermit.
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.* val semaphore = Semaphore(2) // Vienu metu gali dirbti 2 korutinos suspend fun doLimitedWork(id: Int) { semaphore.withPermit { println("Korutina $id įgijo leidimą. Dirba...") delay(100) // Darbo imitacija println("Korutina $id paleidžia leidimą.") } } suspend fun main() = coroutineScope { repeat(5) { i -> launch { doLimitedWork(i) } } } -
Atomarinės operacijos (
kotlinx.coroutines.atomiciš)- Užtikrina srauto saugias operacijas primitives ir nuorodose.
- Naudoja žemo lygio CPU instrukcijas (CAS - Compare-and-Swap).
- Tinka paprastoms operacijoms be aiškių užraktų.
import kotlinx.coroutines.atomic.AtomicInt import kotlinx.coroutines.* val atomicCounter = AtomicInt(0) suspend fun atomicIncrement() { atomicCounter.incrementAndGet() } suspend fun main() = coroutineScope { repeat(10_000) { launch { atomicIncrement() } } println(atomicCounter.value) // Tikimės 10000 } -
Bendrai naudojamos duomenų struktūros vieno srauto dispečeriu
- Labiausiai paprastas požiūris.
Dispatchers.Default.limitedParallelism(1)arbanewSingleThreadContextleidžia vykdyti korutinas vieno srauto kontekste, garantuojant eilės vykdymą ir išvengiant duomenų varžybų. Tai nėra aiškus sinchronizacijos primitivas, bet užtikrina sinchronizaciją serializacijos būdu.
import kotlinx.coroutines.* val mySingleThreadContext = newSingleThreadContext("SingleThread") var sharedData = mutableListOf<Int>() suspend fun addToSharedData(value: Int) { sharedData.add(value) // Saugu, nes vykdoma viename sraute } suspend fun main() = withContext(mySingleThreadContext) { repeat(10_000) { launch { addToSharedData(it) } } println(sharedData.size) // Tikimės 10000 } - Labiausiai paprastas požiūris.
-
Kanalai
- Nėra sinchronizacijos primitivas, bet gali būti naudojami saugiam duomenų perdavimui tarp korutinų, kas netiesiogiai sprendžia prieigos prie perduodamų duomenų problemas.
- Suteikia būdą perduoti duomenų srautą iš vienos korutinos į kitą.
Pasirinkimas priklauso nuo naudojimo scenarijaus. Mutex ir Semaphore siūlo klasikinius blokavimo mechanizmus, Atomarinės operacijos yra efektyvios paprastoms atominėms atnaujinimams, o vieno srauto dispečeriai patogūs, kai prieiga prie bendrų duomenų turi būti griežtai serializuota. Kanalai naudojami komunikacijai ir koordinacijai, o ne tiesiogiai bendrų išteklių apsaugai.