自旋锁抛出同步锁异常

19

我正在尝试使用SpinLock,但是即使在单线程的控制台应用程序中,甚至是这个最基本的代码,在调用SpinLock.Exit()时也会抛出以下异常。

System.Threading.SynchronizationLockException was unhandled by user code
  Message=The calling thread does not hold the lock.  Source=mscorlib

这里是完整的源代码...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication48
{
    class Program
    {
        static readonly SpinLock SpinLock = new SpinLock();
        static void Main(string[] args)
        {
            bool lockTaken = false;
            try
            {
                SpinLock.Enter(ref lockTaken);
                if (lockTaken)
                    Console.WriteLine("Lock taken");
            }
            finally
            {
                if (lockTaken)
                    SpinLock.Exit();
            }
            Console.WriteLine("Done");
        }
    }
}
1个回答

32

SpinLock是一个结构体,并且您正在从只读字段中读取它。 C#规范指出,在这种情况下,为了调用可能会改变状态的函数,必须将结构体复制到可变局部变量中。这在幕后发生。

您对Enter和Exit的调用发生在您锁的新副本上。因此,Enter正在操作一个未锁定的锁。

不要使SpinLock变量只读,因为它正在被修改。


啊,所以在值类型中使用“readonly”不仅指定该字段不可分配,而且意味着该值是不可变的,并且为了确保这一点,在读取它时会复制该值。 - Peter Morris
3
哇!太感谢了!如果没有你聪明的解释,我会花费数天来找到这个答案。非常感谢! - Eric Ouellet
2
哦,需要一个“发送提示”功能,因为这可能只是为我节省了数天的挫败感。 - Nick
哦,那真是折磨人啊;谢谢。他们真的需要将只读 SpinLock 字段添加到 Roslyn 中。 - Jason C
嘿,看这个,更好的:https://github.com/dotnet/runtime/issues/33773(通过https://github.com/dotnet/roslyn/issues/53620)。 - Jason C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接