问题
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)
edit
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) ?
回答1:
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.
回答2:
Locking with Interlocked
is done by replacing a new value with an old value only if the old value hasn't changed. If it has we try again until it doesn't (spinning).
This can be used to replace fine grained locks that only update a single value or to implement a lightweight locking mechanism like SpinLock.
Example:
private int _value;
int oldValue;
int originalValue;
do
{
oldValue = _value;
originalValue = Interlocked.CompareExchange(ref _value, newValue, oldValue);
}
while (originalValue != oldValue);
Instead of:
lock(_lock)
{
_value = newValue;
}
来源:https://stackoverflow.com/questions/23842935/c-sharp-interlocked-functions-as-a-lock-mechanism