How to implement custom TaS-Lock in C #?

So, for the assignment, we need to be able to use C # -Lock or use the self-employed TaS-Lock. What I read about TaS-Locks is that it uses 1 atomic step to read and write the value. We were asked to use the Interlocked class in C # for this.

So far this is what I have, but it seems to lead to inconsistent answers:

public interface Lock { void Lock(); void Unlock(); } public class C_Sharp_Lock : Lock { readonly Object myLock = new object(); public void Lock() { Monitor.Enter(myLock); } public void Unlock() { Monitor.Exit(myLock); } } public class Tas_Lock : Lock { int L = 0; public void Lock() { while (0 == Interlocked.Exchange(ref L, 1)) { }; } public void Unlock() { Interlocked.Exchange(ref L, 0); } } 

Does anyone know what I'm doing wrong here?

Edit : as an answer to Kevin's question:

I changed it to the following:

 public class Tas_Lock : Lock { int L = 0; public void Lock() { while (0 == Interlocked.CompareExchange(ref L, 1, 0)) { }; } public void Unlock() { Interlocked.Exchange(ref L, 0); } } 

However, this still returns inconsistent results.

Change # 2: Changes to C # lock:

 public class C_Sharp_Lock : Lock { readonly Object myLock = new object(); bool lockTaken = false; public void Lock() { Monitor.Enter(myLock, ref lockTaken); } public void Unlock() { if (lockTaken) Monitor.Exit(myLock); } } 
+5
source share
1 answer

You misunderstand how Interlocked.CompareExchange works. It automatically changes the value if it was previously equal to the provided comparison and returns the previous value .

In short, Interlocked.CompareExchange(ref L, 1, 0) will be:

  • Check if L 0 is
  • If L is 0, then it will set L to 1 and return the previous value (0)
  • If L is not equal to 0 (and therefore equal to 1), then it will return the previous value (1)

From there you need to do a loop until Interlocked.CompareExchange returns 0 (this means that the lock has been received). In your code, you are waiting for Interlocked.CompareExchange return 0.

Fixed Code:

 public class Tas_Lock { int L = 0; public void Lock() { while (0 != Interlocked.CompareExchange(ref L, 1, 0)) { } } public void Unlock() { Interlocked.Exchange(ref L, 0); } } 

Two things to note:

  • Interlocked.Exchange in Unlock can be replaced by a faster Volatile.Write (or even, albeit well-reasoned, simple entry)
  • If not for the assignment, you could use the built-in SpinLock class, which already does all this in an optimized way
+5
source

Source: https://habr.com/ru/post/1260536/


All Articles