I was banging my head against a wall when I found this post by Jerome Laban about the volatile keyword. I made the mistake of thinking that volatile would be sufficient in this situation:
and I was surprised when some of my unit tests were not running correctly (on a side note, I usually unit test multi-threading issues by issuing a command 100 or 1000 times. I’m interested in hearing how you test that kind of stuff).
Turns out that if I thought about it a little more I would have realized that this won’t do what you (might) expect. You see the volatile keyword just tells the system never to cache this variable – that’s especially important in multi-processor systems (and who doesn’t have at least 2 cores nowadays?) where each processor might have a different cache of the variable value.
So by using the volatile keyword you’re telling the processor to always get the latest version of the variable from memory. So why is the above code not thread safe?
Well, remember that the incrementing a variable is a multi-step process:
- load variable into a register
- save back from the register
Now the thread might pause at any point in this process! What happens if Thread A does step 1 and then gets paused, then Thread 2 does step 1? After both threads run, _counter will only have incremented by 1! So even though you’re always reading the current value, your increment isn’t thread safe.
So this is where you say “hey – I don’t really need the volatile keyword here. I need a lock instead”. And you’d be right: