Firstly, threading is tricky ;-p
Yes, despite all the rumours to the contrary, it is required to either use lock
or volatile
(but not both) when accessing a bool
from multiple threads.
For simple types and access such as an exit flag (bool
), then volatile
is sufficient – this ensures that threads don’t cache the value in their registers (meaning: one of the threads never sees updates).
For larger values (where atomicity is an issue), or where you want to synchronize a sequence of operations (a typical example being “if not exists and add” dictionary access), a lock
is more versatile. This acts as a memory-barrier, so still gives you the thread safety, but provides other features such as pulse/wait. Note that you shouldn’t use a lock
on a value-type or a string
; nor Type
or this
; the best option is to have your own locking object as a field (readonly object syncLock = new object();
) and lock on this.
For an example of how badly it breaks (i.e. looping forever) if you don’t synchronize – see here.
To span multiple programs, an OS primitive like a Mutex
or *ResetEvent
may also be useful, but this is overkill for a single exe.