Home > Back-end >  Thread-safe access to the same variable from different flows (Kotlin)
Thread-safe access to the same variable from different flows (Kotlin)

Time:01-17

Is this code thread safe? Do I need a synchronized block or something like that? source1 and source2 endless Kotlin Flow

viewModelScope.launch {
    var listAll = mutableListOf<String>()
    var list1 = mutableListOf<String>()
    var list2 = mutableListOf<String>()

    launch {
        source1.getNames().collect { list ->
            list1 = list

            listAll = mutableListOf()
            listAll.addAll(list1)
            listAll.addAll(list2)

            //then consume listAll as StateFlow or return another flow with emit(listAll)
        }
    }

    launch {
        source2.getNames().collect { list ->
            list2 = list

            listAll = mutableListOf()
            listAll.addAll(list2)
            listAll.addAll(list1)

            //then consume listAll as StateFlow or return another flow with emit(listAll)
        }
    }
}

CodePudding user response:

This code is not thread safe.

However, it is called from viewModelScope.launch which runs on Dispatchers.Main by default. So your inner launch blocks will be called sequentially. This means that after all you will get the result which is produced by second launch block.

To achieve asynchronous behavior, you want to use viewModelScope.launch(Dispatchers.Default). Your code will probably fire concurrent modification exception in that case.

To synchronize it, you may want to use Java's Collections.synchronizedList which blocks the list while one thread is performing operations with it, so the other thread are not able to perform modifications.

Or perform synchronizing manually using Mutex.

 val mutex = Mutex()  

 viewModelScope.launch(Dispatchers.Default) {       

     launch {
         mutex.withLock {
             ... // Your code 
         }    
     }

     launch {
         mutex.withLock {
             ... // Your code 
         }    
     }
 }

Read official Kotlin guide to shared mutable state

After all, I am struggling to imagine real life example in which you will actually use that code. You probably don't need asynchronous behavior, you will be fine without using two launch blocks. Or you should rethink your design to avoid need of manual synchronization of two coroutines.

  • Related