Sobes.tech
Middle+

Come sincronizzare le coroutine su Android?

sobes.tech AI

Risposta dell'AI

Per sincronizzare le coroutine in Android, si possono usare diversi approcci a seconda del compito specifico:

  • Join: Attendere il completamento di un'altra coroutine.

    // Avviare la prima coroutine
    val job1 = CoroutineScope(Dispatchers.Default).launch {
        delay(1000)
        println("Job 1 completato")
    }
    
    // Avviare la seconda coroutine
    val job2 = CoroutineScope(Dispatchers.Default).launch {
        delay(500)
        println("Job 2 completato")
    }
    
    // Attendere la fine di entrambe le coroutine
    job1.join()
    job2.join()
    
    println("Tutti i lavori completati")
    
  • Await: Attendere il risultato di un'operazione asincrona rappresentata da Deferred.

    // Operazione asincrona che restituisce un risultato
    val deferredResult = CoroutineScope(Dispatchers.Default).async {
        delay(1000)
        "Risultato da async"
    }
    
    // Attendere il risultato
    val result = deferredResult.await()
    println(result)
    
  • CoroutineScope.coroutineScope: Creare un nuovo ambito di visibilità che termina solo dopo il completamento di tutte le coroutine figlie. Utile per la concorrenza strutturata.

    suspend fun doParallelWork() {
        coroutineScope { // Creare un nuovo scope di concorrenza strutturata
            launch { delay(1000); println("Task 1 completato") }
            launch { delay(500); println("Task 2 completato") }
        } // Questo punto sarà raggiunto solo dopo il completamento di task 1 e task 2
        println("Tutte le attività parallele completate")
    }
    
  • Semantica degli attori (Channel): Per lo scambio di messaggi e la sincronizzazione dell'accesso a dati modificabili tra coroutine.

    // Creare un canale per scambiare Int
    val channel = Channel<Int>()
    
    CoroutineScope(Dispatchers.Default).launch {
        // Inviare dati nel canale
        for (i in 1..5) {
            channel.send(i)
        }
        channel.close() // Chiudere il canale dopo l'invio
    }
    
    CoroutineScope(Dispatchers.Default).launch {
        // Ricevere dati dal canale
        for (value in channel) {
            println("Ricevuto $value")
        }
    }
    
  • Mutex: Per garantire accesso esclusivo a una risorsa condivisa.

    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock { // Acquisire il mutex
            counter++
            // Il mutex verrà automaticamente rilasciato all'uscita dal blocco
        }
    }
    

La scelta del metodo dipende da cosa si deve sincronizzare esattamente: attendere il completamento, ottenere un risultato, gestire attività parallele, scambiare dati o accesso esclusivo. coroutineScope è l'approccio raccomandato di default per la concorrenza strutturata.