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.