Thread Safety Experiments in Kotlin
--
Disclaimer: All opinions are my own
Concurrency is hard! Like many of you, I spent a fair amount of time on it in undergrad, and only when I was forced to after that.
So today I’d like to run through some of the tools available for shared mutable state management in Kotlin. As has become my habit, some of the examples will be straight from the article and others will be modified for better understanding.
The first one is this example, basically a very non-thread safe example.
This one is pretty mind-bending to me at first. It typically prints out less than the 100000 you would expect.
The reason is that reading and writing counter
are not atomic together. So even though it looks like you’re executing one statement, counter++
, you’re actually executing two statements. A slightly modified example (and reduced threads/iterations to control total output) makes this easier to see.
Note depending on your luck the threads might actually all execute in order and give you an ending counter of 50. But typically I see something like 30.
The reason is that you might have a thread that reads a low value, gets suspended while other threads are increasing the value, then adds the value.
The worst-case scenario for this is
- All threads read 0
- All threads complete, except threads 1 and 2
- Thread 1 has 1 iteration left, thread 2 still hasn’t written its first increment
- Thread 2 writes
1
, its first iteration - Thread 1 reads
1
for its last iteration - Thread 2 completes
- Thread 1 writes
2
for its last iteration