【问题标题】:Value type cannot be locked Using LOCK C#无法使用 LOCK C# 锁定值类型
【发布时间】:2016-07-22 06:58:11
【问题描述】:

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

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

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

【问题讨论】:

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


    【解决方案1】:

    原始值类型无处存储有关锁的所需信息。例如,int (Int32) 是 4 个字节的数据仅此而已。另一方面,object 具有相关联的几个头字节,锁定原语可以在需要时延迟存储(特定对象第一次被锁定时)。的确,所有值类型都可以处理作为对象(通过装箱),但这没有用,因为每次调用lock 都会单独装箱,所以你永远不会和同一个对象说话——它不会达到预期的结果。

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

    【讨论】:

    • 在上面的语句中headre字节与同步根记录有关。这里的header字节是什么..
    • @sudhir 标头字节是 object header 的一部分。 object(在堆上)包含一些额外的字节(与有效负载分开)来指示对象是什么类型,以及其他一些东西。其中之一是“同步根”令牌,它是惰性填充的。
    【解决方案2】:

    因为值类型的按值复制语义。

    lock 使用 Monitor.Enter(yourValueTypeVariable) 超越引擎盖。

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

    考虑下面的例子:

    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 类需要同步对象的引用,以确定尝试是否在同一个块上并使用同一个对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-20
      相关资源
      最近更新 更多