This is atomical, so threadsafe
int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0);
if (sync == 0)
It means: if the syncPoint is 0, put it at 1, give me the old value (so 0) and put it in sync (a local variable). Then check if the exchange was done (so if the old value was 0)
What I would make different is instead of
syncPoint = 0;
I would use
Interlocked.Exchange(ref syncPoint, 0);
just to be sure that other threads can immediately see that the "lock" is free, otherwise the current thread could delay "writing" that syncPoint = 0
and no other threads could enter the "lock".
BUT
in the example given this is not a problem: HandleElapsed
is called in response to a event (the Timer probably uses OS timers)... I can't even imagine that after the event has been handled there isn't any code that generates a memory barrier (inside the .NET code or inside the Windows OS code), so that the syncPoint
update will be made visible to other threads. The only difference is that perhaps it will be made visible "some hundred lines below that point" instead of "immediately now".
Let's check this theory: from here
If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.
So, the event is fired on a new ThreadPool
thread... That after the event is surely returned to the ThreadPool
... Ok... There is surely a MemoryBarrier
somewhere (at least to return the thread to the ThreadPool
or to Sleep
if the same thread is used more than once)