Sobes.tech
Middle+

Jak synchronizować korutyny w Androidzie?

sobes.tech AI

Odpowiedź od AI

Aby zsynchronizować korutyny w Androidzie, można użyć kilku podejść, w zależności od konkretnego zadania:

  • Join: Oczekiwanie na zakończenie innej korutyny.

    // Uruchamiamy pierwszą korutynę
    val job1 = CoroutineScope(Dispatchers.Default).launch {
        delay(1000)
        println("Job 1 zakończony")
    }
    
    // Uruchamiamy drugą korutynę
    val job2 = CoroutineScope(Dispatchers.Default).launch {
        delay(500)
        println("Job 2 zakończony")
    }
    
    // Czekamy na zakończenie obu korutyn
    job1.join()
    job2.join()
    
    println("Wszystkie zadania zakończone")
    
  • Await: Oczekiwanie na wynik operacji asynchronicznej reprezentowanej przez Deferred.

    // Operacja asynchroniczna zwracająca wynik
    val deferredResult = CoroutineScope(Dispatchers.Default).async {
        delay(1000)
        "Wynik z async"
    }
    
    // Czekamy na wynik
    val result = deferredResult.await()
    println(result)
    
  • CoroutineScope.coroutineScope: Tworzenie nowego zakresu, który zakończy się dopiero po zakończeniu wszystkich dzieci korutyn. Przydatne do strukturalnej konkurencji.

    suspend fun doParallelWork() {
        coroutineScope { // Tworzymy nowy scope strukturalnej konkurencji
            launch { delay(1000); println("Zadanie 1 zakończone") }
            launch { delay(500); println("Zadanie 2 zakończone") }
        } // Punkt ten osiągnięty tylko po zakończeniu zadania 1 i 2
        println("Wszystkie zadania równoległe zakończone")
    }
    
  • Semantyka aktorów (Channel): Do wymiany wiadomości i synchronizacji dostępu do modyfikowalnych danych między korutynami.

    // Tworzymy kanał do wymiany Int
    val channel = Channel<Int>()
    
    CoroutineScope(Dispatchers.Default).launch {
        // Wysyłanie danych do kanału
        for (i in 1..5) {
            channel.send(i)
        }
        channel.close() // Zamykamy kanał po wysłaniu
    }
    
    CoroutineScope(Dispatchers.Default).launch {
        // Odbieranie danych z kanału
        for (value in channel) {
            println("Odebrano $value")
        }
    }
    
  • Mutex: Zapewnienie wyłącznego dostępu do wspólnego zasobu.

    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock { // Zabezpiecz mutex
            counter++
            // Mutex zostanie automatycznie zwolniony po wyjściu z bloku
        }
    }
    

Wybór metody zależy od tego, co dokładnie trzeba zsynchronizować: oczekiwanie na zakończenie, uzyskanie wyniku, zarządzanie równoległymi zadaniami, wymiana danych czy dostęp wyłączny. coroutineScope jest domyślnie zalecanym podejściem do strukturalnej konkurencji.