Hi guys, Sometimes (pretty infrequently) we’re get...
# getting-started
j
Hi guys, Sometimes (pretty infrequently) we’re getting a crash on a piece of code that adds data to a list. It’s pretty simple really, a
private val mutableListOf()
and the code that crashes just
.add
to that list. Exception is:
ArrayIndexOutOfBoundsException
We’re not sure what the issue could be, only idea that comes to mind is 2 threads calling add at the same time. • Anything else worth investigating? • If it’s the most likely issue, is there a solution beside “dont call twice on different threads” • Something like a thread safe list maybe? Thanks! 🙏
s
I think multithreading is very likely to be the cause, based on the symptoms you described 👍
You have a couple of options to make it thread safe; the simplest is to use
Collections.synchronizedList
from Java
j
Seems easy enough 🙂 Any drawback I should be aware of? Out of curiosity, what would the alternatives be? In case it matters, the use case is logging locations in a KML file, the location can come from multiple coroutines/flows in the codebase Also, realizing this is not quite a kotlin specific question any longer, sorry about that 😕
m
Its definitely threaded access to the list like @Sam mentioned. An alternative would be:
Copy code
synchronized(listToAddTo) {
    listToAddTo.add(thingYouAreAdding)
}
👍 1
s
Drawbacks of synchronized lists: • Synchronization is slow • It’s not coroutine-aware, so waiting coroutines will be blocked, not suspended • It doesn’t prevent other threading issues, like concurrent modification while iterating Alternatives could be: • Channels, if you’re using coroutines • Other thread-safe lists like
CopyOnWriteArrayList
and
LinkedBlockingQueue
k
Can't you just wrap the operation in a mutex?
Then you would just suspend the coroutine, so it should be better than using synchronized
k
I was thinking the same, a Mutex should do the work and make the code suspendable
j
Ok, thanks guys 🙂 Just making sure I get this correctly:
Copy code
private val myList = mutableListOf<Data>()

fun logData(data: Data) {
    myList.add(data)
}
Becomes:
Copy code
private val myList = mutableListOf<Data>()
private val mutex = Mutex()

suspend fun logData(data: Data) {
    mutex.withLock {
         myList.add(data)
    }
}
Correct?
👍 1