So for an assignment we need to have the option to either use the C#-Lock or use a self-implemented TaS-Lock. What I've read about TaS-Locks is that it uses 1 atomic step to both read and write a value. It was suggested to us that we use the Interlocked class in C# for this.
因此,对于一个作业,我们需要选择使用c#锁或使用自实现的任务锁。我读到的关于任务锁的内容是,它使用1原子步骤来读取和写入一个值。有人建议我们在c#中使用互锁类。
So far this is what I've got, but it seems to result in 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 a response to Kevin:
编辑:作为对Kevin的回应:
I've 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.
然而,这仍然返回不一致的结果。
Edit #2: Changes to C# lock:
编辑#2:修改c#锁:
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);
}
}
1 个解决方案
#1
5
You're misunderstanding the way Interlocked.CompareExchange
works. It swaps atomatically a value if it's previously equal to the provided comparand, and returns the previous value.
你误解了相互联系的方式。CompareExchange作品。如果先前的值与提供的比较值相等,它将自动交换一个值,并返回先前的值。
In short, Interlocked.CompareExchange(ref L, 1, 0)
will:
简而言之,联锁。CompareExchange(ref L, 1,0)将:
- Check whether L is equal to 0
- 检查L是否等于0
- If L is equal to 0, then it will set L to 1 and return the previous value (0)
- 如果L等于0,那么它将把L设为1,并返回上一个值(0)
- If L isn't equal to 0 (and therefore is equal to 1), then it will return the previous value (1)
- 如果L不等于0(因此等于1),则返回先前的值(1)
From there, what you should do is loop until Interlocked.CompareExchange
returns 0 (which means that the lock was acquired). In your code, you're waiting while Interlocked.CompareExchange
returns 0.
从这里开始,您应该做的是循环,直到互锁。CompareExchange返回0(这意味着锁被获取)。在您的代码中,您正在等待,同时进行互锁。CompareExchange返回0。
The 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:
两个注意事项:
- The
Interlocked.Exchange
inUnlock
could be replaced by a fasterVolatile.Write
(or even, though arguable, a simple write) - 联锁。解锁的交换可以被更快的挥发性取代。写(或者,即使是有争议的,简单的写)
- If it wasn't for an assignment, you could use the built-in class
SpinLock
, which already does all that stuff in an optimized way - 如果不是赋值,您可以使用内置的类SpinLock,它已经以优化的方式完成了所有的工作。
#1
5
You're misunderstanding the way Interlocked.CompareExchange
works. It swaps atomatically a value if it's previously equal to the provided comparand, and returns the previous value.
你误解了相互联系的方式。CompareExchange作品。如果先前的值与提供的比较值相等,它将自动交换一个值,并返回先前的值。
In short, Interlocked.CompareExchange(ref L, 1, 0)
will:
简而言之,联锁。CompareExchange(ref L, 1,0)将:
- Check whether L is equal to 0
- 检查L是否等于0
- If L is equal to 0, then it will set L to 1 and return the previous value (0)
- 如果L等于0,那么它将把L设为1,并返回上一个值(0)
- If L isn't equal to 0 (and therefore is equal to 1), then it will return the previous value (1)
- 如果L不等于0(因此等于1),则返回先前的值(1)
From there, what you should do is loop until Interlocked.CompareExchange
returns 0 (which means that the lock was acquired). In your code, you're waiting while Interlocked.CompareExchange
returns 0.
从这里开始,您应该做的是循环,直到互锁。CompareExchange返回0(这意味着锁被获取)。在您的代码中,您正在等待,同时进行互锁。CompareExchange返回0。
The 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:
两个注意事项:
- The
Interlocked.Exchange
inUnlock
could be replaced by a fasterVolatile.Write
(or even, though arguable, a simple write) - 联锁。解锁的交换可以被更快的挥发性取代。写(或者,即使是有争议的,简单的写)
- If it wasn't for an assignment, you could use the built-in class
SpinLock
, which already does all that stuff in an optimized way - 如果不是赋值,您可以使用内置的类SpinLock,它已经以优化的方式完成了所有的工作。