c# - 如何实现自己的锁定机制

标签 c# .net concurrency locking

对于一个赋值(如果你想知道它是为了并发)——我必须实现我自己的锁

(更具体:TaS、TTas 和 Array-Lock,如“多处理器编程的艺术”中所述)

我尝试了一些在线测试输入和输出方案(太糟糕了,他们需要很长时间才能尝试)。

Your program is to count 9-digit numbers that pass a certain test

(它在荷兰语中被称为 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); }
}

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);
    }
}

现在在我刚刚使用的并行部分:

theLock.Lock();
counter++;
theLock.Unlock();

但每次我得到的结果都略有不同。

有什么明显的我做错了吗?

最佳答案

汉斯是对的。您的原子获取和设置 bool 值似乎是正确的——事实上,在我看来它有点过度设计。而且锁似乎也是正确的,因为您已经为自己构建了一个可能非常低效的“自旋锁”。 (也就是说,所有等待的线程都只是坐在那里,形成一个紧密的循环,询问“我可以走了吗?我可以走了吗?”而不是在轮到它们之前进入休眠状态。)

不正确的是,您的锁不能保证任何两个都具有“counter” View 的线程都具有一致“counter” View 。两个线程可能在不同的处理器上,而那些不同的处理器可能在它们的缓存中有不同的“计数器”副本。缓存的副本将被更新,并且只是偶尔写回主内存,从而有效地“丢失”了一些增加。

在 C# 中锁定的真正实现确保了一个完整的内存屏障被强加,这样读取和写入就不能“在时间上向前和向后”移动穿过栅栏。这给了处理器一个提示,即它们不需要如此聪明地如此积极地缓存“计数器”。

关于c# - 如何实现自己的锁定机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7589469/

相关文章:

c# - 无法将类型 'string' 隐式转换为 'System.DateTime'

c# - SHA-256 NodeJS 与 .NET C#

c# - 如何编码 .NET 中的结构以供 native 代码使用?

c# - 如何将 XML 数据加载到数据结构中?

c# - 我如何测试 ModelState?

c# - ADO 异常操作数类型冲突

.net - Memcached 是否可以与 ASP.NET 状态服务器互换?

go - sync.Map 是这个用例的正确工具吗?或者是 RW 互斥锁更好

java - 如何删除要在 ConcurrentSkipListMap 中键入的元素?

java - 在读取器/写入器场景中,我是否需要使两个变量都为 volatile ?