Sobes.tech
Middle+

How to synchronize coroutines in Android?

sobes.tech AI

Answer from AI

To synchronize coroutines in Android, several approaches can be used depending on the specific task:

  • Join: Waiting for another coroutine to complete.

    // Launch the first coroutine
    val job1 = CoroutineScope(Dispatchers.Default).launch {
        delay(1000)
        println("Job 1 done")
    }
    
    // Launch the second coroutine
    val job2 = CoroutineScope(Dispatchers.Default).launch {
        delay(500)
        println("Job 2 done")
    }
    
    // Wait for both coroutines to finish
    job1.join()
    job2.join()
    
    println("All jobs done")
    
  • Await: Waiting for the result of an asynchronous operation represented by Deferred.

    // Asynchronous operation returning a result
    val deferredResult = CoroutineScope(Dispatchers.Default).async {
        delay(1000)
        "Result from async"
    }
    
    // Await the result
    val result = deferredResult.await()
    println(result)
    
  • CoroutineScope.coroutineScope: Creating a new scope that only finishes after all child coroutines complete. Useful for structured concurrency.

    suspend fun doParallelWork() {
        coroutineScope { // Create a new structured concurrency scope
            launch { delay(1000); println("Task 1 done") }
            launch { delay(500); println("Task 2 done") }
        } // This point is reached only after task 1 and task 2 are finished
        println("All parallel tasks done")
    }
    
  • Actor semantics (Channel): For message exchange and synchronization of access to mutable data between coroutines.

    // Create a channel for exchanging Int
    val channel = Channel<Int>()
    
    CoroutineScope(Dispatchers.Default).launch {
        // Send data to the channel
        for (i in 1..5) {
            channel.send(i)
        }
        channel.close() // Close the channel after sending
    }
    
    CoroutineScope(Dispatchers.Default).launch {
        // Receive data from the channel
        for (value in channel) {
            println("Received $value")
        }
    }
    
  • Mutex: To ensure exclusive access to a shared resource.

    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock { // Acquire the mutex
            counter++
            // Mutex will be automatically released when leaving the block
        }
    }
    

The choice of method depends on what exactly needs to be synchronized: waiting for completion, obtaining a result, managing parallel tasks, exchanging data, or exclusive access. coroutineScope is the recommended default approach for structured concurrency.

How to synchronize coroutines in Android? — Android - sobes.tech