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 ?
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.
We can add elements in a mutable list using the add() function, and remove an elements using remove () function.
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.
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.
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 Map
s; 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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With