【问题标题】:lock(variable) - conflicting explanation of the variable [closed]lock(variable) - 对变量的冲突解释[关闭]
【发布时间】:2014-06-23 20:28:31
【问题描述】:

The docs不解释。他们只说应该锁定什么,不应该锁定什么。

here 看来,所有线程都应该使用同一个对象才能使锁起作用。从here 看来,这正是应该避免的,以防止死锁。

请记住,我可能会误解整个锁定问题,因为我只是 asked a question 关于如何“锁定”一个变量并得到我认为的 根本无法实现(锁定代码除外)。

【问题讨论】:

  • 不解释什么? “lock 关键字通过获取给定对象的互斥锁,执行语句,然后释放锁,将语句块标记为临界区。” - 似乎很清楚。请注意文档中使用的是 object,而不是 variable
  • lock for a given object - 那。
  • 你能显示你试图锁定的代码吗?线程可能很复杂。除了阅读这些线程中提供的答案之外,很难给您答案。 IMO-不,您不应该 lock(this){...} 然后在其他示例中,该对象应作为字段而不是变量,如该线程的答案中所述。使用示例代码帮助您正确锁定会容易得多
  • 是的,锁定解决了竞争条件并引入了死锁的风险。赢一些,输一些。您必须以完全正确的方式使用它们,这就是为什么这不是一个好问题。细节很重要。
  • 反对票不必解释。但是给你一个想法:一个好的问题可以独立存在,并且更具体和/或更详细。它可能/应该是对您之前的问题的修改。

标签: c# .net multithreading


【解决方案1】:

将锁想象成在某些会议中使用的“谈话棒”。谁拿着棍子,谁就可以说话。任何想说话的人都必须等到说话者放下棍子。

当一段代码获得一个对象上的锁时,任何其他请求锁在同一对象上的代码都必须等待,直到原始代码释放锁。

那么你应该锁定哪个对象?这在很大程度上取决于上下文。经验法则是您锁定一个可能影响代码块的其他人也可以锁定的对象。如果你正在更新一个集合,那么你可以以ICollection.SyncRoot 为例。

OP 编辑​​(希望正确) “任何想说话的人” - 作为“那根棍子”的说话者。 (任何人都可以说话。) 至于问题中的第二个链接 - 它指的是一个锁等待第二个,而第二个正在等待第一个的问题。

【讨论】:

  • 谢谢。但是,那么,我的问题中链接的第二个答案似乎(是的,我知道,似乎)正好相反呢?
  • 好的,我在回答中说错了一点。我会修改它。
  • 我刚刚编辑了您的答案(并接受了它。)我希望没关系。如果没有 - 请回滚。再次感谢。
  • 您的编辑只是解释了说话棒的用途,这很好。希望对您有所帮助。
【解决方案2】:

lock 应该用于任何共享资源。我所说的“共享资源”是指由多个线程访问的任何东西。

锁所做的只是:

  1. 传入线程想要访问一段代码,遇到锁
  2. 锁为空,允许线程进入
  3. 线程被关闭
  4. 另一个线程想要访问相同的代码(或锁定在同一变量上的代码),遇到了锁
  5. 变量已被锁定,线程必须等待
  6. 原线程切换回,退出锁定代码
  7. 第二个线程切换回来,执行锁定的代码

如果有可能有线程在一个锁中并同时等待另一个锁,然后等待第一个锁,你就会遇到死锁情况。通常你不会“嵌套”你的锁来避免这个问题。此外,为了性能,如果没有别的,你很少锁定与另一个变量相同的变量,除非你实际上有两个部分都依赖于不同时执行的代码(如果是这样的话,可能是一个糟糕的设计:))

【讨论】:

  • 谢谢。我接受了另一个答案,因为它让我更清楚。但你的回答也有帮助。 +1。
【解决方案3】:

锁定某些东西是为了保护一块共享内存。因此,您必须对要保护的特定元素使用相同的 SyncRoot... 但是,假设您有 3 个需要保护的对象,它们之间没有任何关系:

A a = new A();
B b = new B();
C c = new C();

那么没有理由对所有 3 个使用相同的 SyncRoot。事实上,如果它们真的是分开的,那将是低效的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-03
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多