因此,对于赋值,我们需要选择使用C#-Lock或使用自实现的TaS-Lock。我读过的有关TaS-Locks的内容是它使用1个原子步骤来读取和写入值。有人建议我们在C#中使用Interlocked类。
到目前为止,这是我所得到的,但似乎导致答案不一致:
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);
}
}
有谁知道我在这里做错了什么?
编辑:作为对凯文的回复:
我已将其更改为以下内容:
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);
}
}
然而,这仍会导致不一致的结果。
编辑#2:对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);
}
}
答案 0 :(得分:5)
你误解了Interlocked.CompareExchange
的工作方式。如果它之前等于提供的比较,并返回之前的值,则会自动交换值。
简而言之,Interlocked.CompareExchange(ref L, 1, 0)
将:
从那里,你应该做的是循环直到 Interlocked.CompareExchange
返回0(这意味着获得了锁)。在您的代码中,当 Interlocked.CompareExchange
返回0时,您正在等待。
固定代码:
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);
}
}
有两点需要注意:
Interlocked.Exchange
中的Unlock
可以被更快的Volatile.Write
取代(甚至可以说是一个简单的写法)SpinLock
,它已经以优化的方式完成所有这些工作