Rub*_*ben 5 .net c# concurrency locking
对于一个赋值(如果你想知道它是并发的) - 我必须实现自己的锁
(更具体:TaS,TTas和Array-Lock,如"多处理器编程的艺术"中所述)
我尝试过一些在线测试输入和输出方案(太糟糕了,他们需要很长时间才能尝试).
您的程序将计算通过特定测试的9位数字
(它在荷兰语中称为elfproef,我不知道英语对等,对不起).
有时我的号码略有不同,这表明我的锁不能100%正常工作.
我已经实现了这样的锁:
interface Lock
{
void Lock();
void Unlock();
}
class TaSLock : Lock
{
AtomicBool state = new AtomicBool(false);
void Lock.Lock()
{ while (state.getAndSet(true)); }
void Lock.Unlock()
{ state.getAndSet(false); }
}
Run Code Online (Sandbox Code Playgroud)
在AtomicBool与一个实现integer,因为Interlocked类不具备操作Boolean变量.这在内存使用方面不是最佳的,但它不会(或不应该)对速度有影响.
class AtomicBool
{
int value;
static int True = 1, False = -1;
public AtomicBool(bool value)
{
if (value) this.value = True;
else this.value = False;
}
public void set(bool newValue)
{
if (newValue) Interlocked.Exchange(ref value, True);
else Interlocked.Exchange(ref value, False);
}
public bool getAndSet(bool newValue)
{
int oldValue;
if (newValue) oldValue = Interlocked.Exchange(ref value, True);
else oldValue = Interlocked.Exchange(ref value, False);
return (oldValue == True);
}
public bool get()
{
return (Interlocked.Add(ref value, 0) == 1);
}
}
Run Code Online (Sandbox Code Playgroud)
现在在我刚使用的并行部分中:
theLock.Lock();
counter++;
theLock.Unlock();
Run Code Online (Sandbox Code Playgroud)
但每次我得到的结果都略有不同.
有什么明显的东西我做错了吗?
汉斯是对的.你的原子获取和设置布尔似乎是正确的 - 事实上,在我看来,它有点过度设计.锁定似乎也是正确的,因为你已经为自己建立了一个潜在的低效"自旋锁".(也就是说,所有等待的线程只是紧紧地坐在那里问"我可以去吗?我可以去吗?"而不是睡觉直到轮到他们.)
不正确的是,你的锁不保证任何两个都具有"计数器"视图的线程都具有一致的"计数器"视图.两个线程可以在不同的处理器上,并且那些不同的处理器可以在其高速缓存中具有不同的"计数器"副本.缓存的副本将被更新,并且仅偶尔写回主存储器,从而有效地"丢失"一些增加.
锁定C#的真正实现确保强制执行全栅栏内存屏障,以便读取和写入不能跨越栅栏"向前和向后移动".这给了处理器一个提示,他们需要不那么聪明地如此积极地缓存"反击".