本文介绍了如何在C#中实现自己的TaS-Lock?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,对于一项分配,我们需要选择使用C#-Lock或使用自行实现的TaS-Lock.我读到的有关TaS-Locks的信息是,它使用1个原子步来读取和写入值.建议我们为此使用C#中的Interlocked类.

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.

到目前为止,这是我所拥有的,但似乎导致答案不一致:

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?

编辑:作为对Kevin的回复:

Edit: As a response to 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.

编辑#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);
    }
}

推荐答案

您误解了 Interlocked.CompareExchange 的工作方式.如果它先前等于提供的比较符,则原子交换一个值,并返回先前的值.

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.

简而言之, Interlocked.CompareExchange(ref L,1,0)将:

  • 检查L是否等于0
  • 如果L等于0,则它将L设置为1并返回上一个值(0)
  • 如果L不等于0(因此等于1),则它将返回前一个值(1)

从那里开始,您应该做的是循环直到 Interlocked.CompareExchange 返回0(这意味着已获得锁).在您的代码中,您正在等待 Interlocked.CompareExchange 返回0.

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.

固定代码:

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

需要注意的两件事:

  • Unlock 中的 Interlocked.Exchange 可以替换为更快的 Volatile.Write (甚至可以说是简单的写法)
  • 如果不是要分配的,则可以使用内置类 SpinLock ,该类已经以优化的方式完成了所有这些工作
  • The Interlocked.Exchange in Unlock could be replaced by a faster Volatile.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

这篇关于如何在C#中实现自己的TaS-Lock?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 16:34