无法锁定值类型使用LOCK C#

时间:2016-07-22 06:58:11

标签: c# multithreading c#-4.0 task-parallel-library

为什么我们不能在Lock C#中使用值类型。我找到了一些原因,但它看起来并不那么便宜:

“请记住,当您为object类型的参数传递值类型时,它会被装箱(包装)为引用类型。这使得每次发生这种情况时它都是一个全新的对象。”

“您无法锁定值类型,因为它没有同步根记录。”

2 个答案:

答案 0 :(得分:5)

原始值类型无处存储有关锁的必需信息。例如,intInt32)是4个字节的数据 而没有别的 。另一方面,对象具有相关的几个头字节,其中可以在需要时(第一次锁定特定对象时)懒惰地存储锁定基元。确实,所有的值类型都可以处理作为对象(通过装箱),但这将是无用的,因为每次调用lock都会将分开包装 ,所以你永远不会谈论同一个对象 - 它不会达到预期的结果。

顺便说一下,我个人认为允许你锁定任意对象是错误的。 Monitor成为实例类型似乎更明显和直接,因此您只能锁定特定类型。那么这个问题就没有实际意义了。

答案 1 :(得分:1)

由于值类型的按值复制语义。

lock使用了Monitor.Enter(yourValueTypeVariable)

两个线程的复制值之间没有任何关系,除了它们可能相等(By Value),这是用于同步目的的无用信息。

考虑以下示例:

static void Main(string[] args)
{
    int x = 5;
    int y = 4 + 1;

    Task.Run(() => Method1(x));
    Task.Run(() => Method2(y));
}

private static void Method1(int lockObject1)
{
    lock (lockObject1)
    {

    }
}

private static void Method2(int lockObject2)
{
    lock (lockObject2)
    {

    }
}

ValueTypes的默认行为是lockObject1lockObject2相等。但你不希望这种行为正确吗?

Monitor类需要同步对象的引用,以确定尝试是否在同一个块上并使用相同的对象。