【问题标题】:Guidelines of when to use locking何时使用锁定的指南
【发布时间】:2011-02-16 07:21:33
【问题描述】:

我想知道开发人员在何时(以及在何处)放置锁是否应遵循任何准则。

例如:我知道这样的代码应该被锁定,以避免另一个线程意外更改 SomeHeapValue 的值的可能性。

class Foo
{
  public SomeHeapObject myObject;
  public void DoSummat(object inputValue_)
  {
    myObject.SomeHeapValue = inputValue_;
  }

}

但是,我的问题是,锁定有多深?例如,如果我们有这样的代码:

class Foo
{
  public SomeHeapObject myObject;
  public void DoSummat(object inputValue_)
  {
    myObject.SomeHeapValue = GetSomeHeapValue();
  }

}

我们应该锁定 DoSummat(...) 方法,还是应该锁定 GetSomeHeapValue() 方法?

在构建多线程代码时,你们有什么需要牢记的准则吗?

【问题讨论】:

    标签: c# multithreading locking


    【解决方案1】:

    我找到的关于锁定和线程的最佳指南是这个页面(这是我在使用锁定和线程时参考的文本):

    http://www.albahari.com/threading/

    您想要“锁定和线程安全”这一段,但也请阅读其余部分,它写得很好。

    【讨论】:

    • 谢谢这很有用...但是为什么所有示例都使用静态成员变量?类成员变量中的线程安全也存在​​问题,对吧?
    • @miguel:可以使用“lock(this)”来锁定实例成员,本页的解释和示例2提供了更多详细信息:msdn.microsoft.com/en-us/library/c5kehkcz%28VS.71%29.aspx。我认为他在 Albahari 网站上使用的是静态的,因为这样他就不必创建一个类的实例,这使得他的示例更短。
    • @miguel:您的锁对象需要跨线程共享才能使用,而静态是一种干净且简单的方法。静态并不是天生的邪恶,只是像旧的全局变量一样被滥用。
    • 专注于静态的另一个原因是,有一种简单的方法可以使任何实例成员免于线程问题 - 永远不要将其暴露给多个线程。这也是大多数 BCL 类对于实例成员来说不是线程安全的原因,除了一些专门用于线程相关任务的类 - 如果它可能永远不会以这种方式使用,为什么要让每个人都支付制造线程安全的成本,但同样如此大多数 BCL 类在静态成员中都是线程安全的。
    • @user218447 这个片段“锁定和线程安全”到底在哪里?我在那个网站上没有找到它
    【解决方案2】:
    • 尽可能少地锁定,但尽可能多地锁定。

    • 尽可能避免使用锁定 - 在 .NET 4.0 中存在不会导致上下文切换的替代方法。

    • 尽量不要多次锁定。相应地构建您的 API。例如队列。 DeQueue - 制作一个替代的 DeQueue(int amount),可以用一个锁将许多项目出队。

    【讨论】:

      【解决方案3】:

      这里有一些指导方针,针对多线程方面相对新手的开发人员:

      1. 确定程序的可变¹共享²状态。在应用程序的生命周期中,哪些可变变量、对象、属性和字段可以被多个线程同时访问或顺序访问?

      2. 使用lock 保护对可变共享状态的所有访问。写读操作都应该受到保护。程序的可变共享状态的单个不受保护的入口点足以使您的锁定方案无效,并使您的程序的行为未定义。

      3. 使用单个 locker 对象来保护所有可变共享状态。仅当每个储物柜都保护完全孤立的可变共享状态孤岛时,才使用多个储物柜。

      4. 尽快解除锁定。确保受保护区域仅包含对共享和可变状态的操作。不要在这些区域内做任何与此状态无关的事情。

      如果您遵循这些准则,您将能够推断您的程序的正确性,并且您的程序将运行得相当好。

      所有这些准则都是可弯曲的,多线程专家可能会因为性能、方便或其他原因不在所有场合都遵循它们而逃脱。但是,在能够正确判断是否可以安全地改变这些准则之前,所需的经验是巨大的。所以要小心,不要过早地对自己过于自信!

      ¹ 可更改,不是只读的。
      ² 多线程共享。

      【讨论】:

        猜你喜欢
        • 2011-02-18
        • 2013-01-24
        • 1970-01-01
        • 2012-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多