Adding items to MutableList asynchronously in kotlin

Viewed 7468

i'm experimenting with Kotlin coroutines.

say i have a mutable list:

val list = mutableListOf<String>()

and i launched 50 couroutines like this:

runBlocking {
    for (i in 1..50) {
        launch(Dispatchers.IO) {
            delay(1000)
            list.add(i.toString())
        }
    }
}
list.forEach { println(it) }

obviously the operations will take about one second despite the "delay(1000)" since they're running asynchronously

those were simple operations that won't cause a problem, but what if i'm writing a lot of big strings at the same time, would some of the operations fail ?

what about writing to a local file using appendText function, would some of the operations fail because the file might be locked by another writing operation ?

2 Answers

The issue here is that the List implementation probably isn't thread-safe: it doesn't guarantee correct operation if two different threads try to update it simultaneously.

(This sort of problem is pernicious, as it'll work fine most of the time, but then fail at some point, usually when heavily loaded.)

I don't know if there are any high-performance thread-safe List implementations.

One option is to take a normal one and put it in a thread-safe wrapper; as long as you only access it via that wrapper, it will enforce thread-safety (by using synchronisation to serialise access, forcing callers to block until they can take their turn).  For example:

val list = java.util.Collections.synchronizedList(mutableListOf<String>())

Another is to use one of the special-purpose thread-safe List implementations, such as CopyOnWriteArrayList.  (Or if you only need iteration and not full List implementation, there's ConcurrentLinkedQueue.)

(Things are better for Maps; the JRE has ConcurrentHashMap which is thread-safe but high-performance, and most methods don't block.)

(I don't know whether File.appendText() is thread-safe or not.  I think the OS usually provides that sort of safety at file level, but I don't know whether that would apply here.)

I think using synchronizedList (blocking thead) it is not good idea. In case of list or writing files you can use Mutex for example (non blocking variant of ReentrantLock from java) see Mutual exclusion

Related