当 C# 4.0 BCL SpinLock 无法获得锁时,它们会自旋/阻塞吗?

发布于 2024-09-08 08:42:54 字数 475 浏览 10 评论 0原文

给出以下代码:

...
private static SpinLock logLock = new SpinLock(false);
...

private static void ThreadFunc()
{
    bool lockTaken = false;
    logLock.Enter(ref lockTaken)
    {
        try
        {
            // do stuff with during an acquired SpinLock
        }
        finally
        {
            logLock.Exit();
        }
    }
}

如果 Enter 块“失败”,因为它在获取锁时收到 false,则当前线程是否像自旋锁一样旋转并等待直到它可以获取它,或者只是绕过此块并且该线程失败?

谢谢,

斯科特

Given the following code:

...
private static SpinLock logLock = new SpinLock(false);
...

private static void ThreadFunc()
{
    bool lockTaken = false;
    logLock.Enter(ref lockTaken)
    {
        try
        {
            // do stuff with during an acquired SpinLock
        }
        finally
        {
            logLock.Exit();
        }
    }
}

If the Enter block "fails" because it receives a false on the lock being acquired, does the current thread spin like a spinlock and wait until it can acquire it or is this block simply bypassed and that thread loses out ?

Thanks,

Scott

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

硪扪都還晓 2024-09-15 08:42:55

SpinLock 基本上只是一个循环,试图将变量设置为特定值。

你可以考虑它的实现如下:(

public struct SpinLock
{
    private volatile bool _Locked;

    public void Acquire()
    {
        while (_Locked)
            ;
        _Locked = true;
    }

    public void Release()
    {
        _Locked = false;
    }
}

当然,上面的代码不是线程安全的,我知道这不是类方法的签名,它只是一个伪代码变体来显示它在做什么)

所以是的,如果 SpinLock 已经处于锁定状态,尝试获取它将会旋转,直到它变得可用。

另请注意,默认情况下(如您的示例中所示),该结构不会跟踪谁拥有锁。这意味着如果一个线程尝试两次获取锁,那么它在第二次尝试时将会与自身发生死锁。

SpinLock 的目的是成为一个开销很小的用户级锁。它不会增加GC压力,也不会分配任何内核同步对象,它只是一个带有几个字段的结构体。

A SpinLock is basically just a loop around trying to set a variable to a specific value.

You could consider its implementation as follows:

public struct SpinLock
{
    private volatile bool _Locked;

    public void Acquire()
    {
        while (_Locked)
            ;
        _Locked = true;
    }

    public void Release()
    {
        _Locked = false;
    }
}

(of course, the above code is not thread-safe, and I know that's not the signature of the methods of the class, it's just a pseudo-code variant to show what it is doing)

So yes, if the SpinLock is already in a locked state, attempting to acquire it will spin until it becomes available.

Also, note that by default (as in your example), the struct does not keep track of who owns the lock. This means that if a thread tries to acquire the lock twice, it will deadlock with itself on the second attempt.

The purpose of SpinLock is to be a user-level lock with little overhead. It does not add GC pressure, nor does it allocate any kernel synchronization object, it's just a struct with a few fields.

一袭白衣梦中忆 2024-09-15 08:42:54

根据定义,SpinLock 会导致线程在等待获取锁时旋转,而不是阻塞。如果 Enter 无法获取锁,则不会“失败”,它只是等待。

Enter 可能无法抛出异常的唯一情况是使用 new SpinLock() 或 new SpinLock(true) 激活线程所有权时。在这种情况下,当线程尝试获取它已经拥有的锁时,会引发异常。在您的情况下,这种情况永远不会发生,因为您创建了禁用跟踪的锁(SpinLock(false))。如果线程尝试重新获取锁,它只会发生死锁。

SpinLock.Enter< 的文档对此进行了描述/a> 方法。

A SpinLock by definition causes the thread to spin while waiting to acquire for a lock rather than blocking. Enter does not "fail" if it can't acquire the lock, it just waits.

The only case where Enter may fail throwing an exception is when thread ownership is activated, using either new SpinLock() or new SpinLock(true). In this case an exception is thrown when a thread tries to acquire a lock it already owns. In your case this can never happen because you created the lock with tracking disabled (SpinLock(false)). If the thread tries to re-acquire the lock it will simply deadlock.

This is described in the documentation of the SpinLock.Enter method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文