Let\'s say that a class has a public int counter
field that is accessed by multiple threads. This int
is only incremented or decremented.
T
lock(...) works, but may block a thread, and could cause deadlock if other code is using the same locks in an incompatible way.
Interlocked.* is the correct way to do it ... much less overhead as modern CPUs support this as a primitive.
volatile on its own is not correct. A thread attempting to retrieve and then write back a modified value could still conflict with another thread doing the same.
"volatile
" does not replace Interlocked.Increment
! It just makes sure that the variable is not cached, but used directly.
Incrementing a variable requires actually three operations:
Interlocked.Increment
performs all three parts as a single atomic operation.
Interlocked functions do not lock. They are atomic, meaning that they can complete without the possibility of a context switch during increment. So there is no chance of deadlock or wait.
I would say that you should always prefer it to a lock and increment.
Volatile is useful if you need writes in one thread to be read in another, and if you want the optimizer to not reorder operations on a variable (because things are happening in another thread that the optimizer doesn't know about). It's an orthogonal choice to how you increment.
This is a really good article if you want to read more about lock-free code, and the right way to approach writing it
http://www.ddj.com/hpc-high-performance-computing/210604448