Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding items to MutableList asynchronously in kotlin

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 ?

like image 414
yazan sayed Avatar asked Jun 27 '19 13:06

yazan sayed


People also ask

How do I add elements to MutableList Kotlin?

To add an element to a Mutable List in Kotlin, we can use add(element), or add(index, element) functions. add(element) adds element to the end of this Mutable List. add(index, element) adds element to this Mutable List at the given index.

How do you add an element to a MutableList?

We can add elements in a mutable list using the add() function, and remove an elements using remove () function.

How do you avoid concurrent updates to a variable in Kotlin?

The golden rule to prevent these issues is to only use immutable objects. An immutable object is an object whose state cannot be changed after its creation. Thus, there is no risk of concurrent modification, and as there is no need of synchronization, we also prevent the risk of deadlocks.

What is the difference between ArrayList and MutableList in Kotlin?

ArrayList is a class that happens to implement the MutableList interface. The only difference is that arrayListOf() returns the ArrayList as an actual ArrayList. mutableListOf() returns a MutableList, so the actual ArrayList is "disguised" as just the parts that are described by the MutableList interface.


1 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.)

like image 70
gidds Avatar answered Sep 18 '22 23:09

gidds