While I was reading about ReaderWriterLockSlim
lock mechanism , There was this guy who suggested that Interlock
Functions can be used for a finer locking
Also, I found here another answer from Marc :
...Writes make their change to a cloned copy, then use Interlocked.CompareExchange to swap the reference (re-applying their change if another thread mutated the reference in the interim).
Well , Currently all I know about Interlocked
object , is that it is used (in a multithreaded environment) to do atomic additions
, compare
, compareExchange
operations. (and I know how to use it)
But (and here is my question) —
Question
How can I use it as a lock ? ( sample code will be much appreciated)
For simplicity , I'm pasting this code ( which is not thread safe - if Go
was called by two threads simultaneously, it would be possible to get a division-by-zero error) :
class ThreadUnsafe
{
static int _val1 = 1, _val2 = 1;
static void Go()
{
if (_val2 != 0) Console.WriteLine (_val1 / _val2);
_val2 = 0;
}
}
How can I use Interlock to replace the lock (which would have solved the problem) ?
Interlocked
is used to implement lockless algorithms and data structures. It's therefore not "finer locking", or even locking at all. It lets you do small and well-defined operations safely in a multi-threaded environment: for instance, if you want two threads to increment the same variable, you can use Interlocked
to do it instead of acquiring a heavyweight lock and using the "regular increment".
However, there are many, many things that you can't do with Interlocked
that you could do under a regular lock. For instance, anything that involves modifying more than one variable atomically generally can't be done with Interlocked
, so you wouldn't be able to use it for your example.
Interlocked
can, however, help developers implement locking mechanism, though you might as well use the built-in ones. Most locks require kernel support to interrupt the blocked thread until the lock becomes available. Therefore, the only kind of lock that you can implement with Interlocked
alone is a spin lock: a lock that threads continually try to acquire until it works.
class InterlockedLock
{
private int locked;
public void Lock()
{
while (Interlocked.CompareExchange(ref locked, 1, 0) != 0)
continue; // spin
}
public void Unlock()
{
locked = 0;
}
}
In this example, locked
is initially zero. When a thread tries to acquire it for the first time, locked
becomes 1, and subsequent threads trying to Lock
it will spin until someone calls Unlock
to make locked
0 again.