【问题标题】:How to properly lock a value type?如何正确锁定值类型?
【发布时间】:2009-01-07 15:52:11
【问题描述】:

我正在阅读有关线程和锁定的信息。您不能(也不应该)锁定值类型是常见的做法。

所以问题是,锁定值类型的推荐方法是什么?我知道有几种方法可以做一件事,但我还没有看到一个例子。虽然 MSDN 论坛上有一个很好的帖子,但我现在似乎找不到。

谢谢

【问题讨论】:

  • 你100%确定在修改值类型对象时需要加锁吗?当这样一个裸对象从一个线程传递到另一个线程时,会生成一个副本,因此线程最终会处理两个不同的对象,这是安全的。

标签: c# locking


【解决方案1】:

为锁使用另一个对象。

int valueType;
object valueTypeLock = new object();

void Foo()
{
    lock (valueTypeLock)
    {
        valueType = 0;
    }
}

【讨论】:

  • 记得把锁对象设为只读,也可以改成其他对象。在这种情况下,共享锁假设可能会失效。
  • 还要注意这个特定的例子是严格的学术性的。没有一个理性的人会在一个简单的int 变量赋值周围实际放置一个lock;分配是原子的,通过在字段声明中使用 volatile 关键字可以更有效、更轻松地确保写入的最新可见性。
【解决方案2】:

您的问题的措辞向我暗示您并不完全理解锁定。你不锁定数据,你锁定是为了保护数据的完整性。您锁定的对象是无关紧要的。重要的是您在代码的其他区域锁定了相同的对象,这些区域会改变受保护的数据。

【讨论】:

    【解决方案3】:

    根据您的情况,您可能可以通过利用 System.Threading.Interlocked 来避免使用锁,Jon 示例中的相同代码变为:

    System.Threading.Interlocked.Exchange(valueType,0)
    

    【讨论】:

      【解决方案4】:

      我总是使用单独的变量来锁定:

      object syncObj = new object();
      
      void Foo()
      {
        lock(syncObj)
        {
          // do some stuff
        }
      }
      

      锁定值类型无论如何都没有意义,因为值类型是不可变的并且不能被修改。锁定 'this' 也是有问题的,因为外部世界可以看到 'this'。

      有关监视器最初打算如何使用的一些信息,请参阅Monitor (synchronization)

      【讨论】:

      • 错误,值类型对象并不是真正不可变的。当我说 int i=0; ++i;我刚刚修改了一个值类型的对象。
      • 不,您为变量分配了一个新值,但您没有改变值类型。值类型是“值”。 1 始终为 1。1+1 是值 2,但您不会将值 1 更改为 2。您可以修改复合值类型(也称为结构),尽管这也被认为是(非常)不好的做法。
      • “值类型是不可变的,不能修改”——这对于原始值类型是正确的,但不是一般的值类型。值类型应该实现为不可变的,但很多不是(例如Rectangle)。在任何情况下,值类型的不变性(或不可变性)不是锁定这种类型没有意义的原因。你不能锁定一个值类型,因为它没有监视器。我发现这个答案非常不准确且具有误导性。
      猜你喜欢
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 2014-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多