C#“lock”关键字:为啥语法需要对象?

Posted

技术标签:

【中文标题】C#“lock”关键字:为啥语法需要对象?【英文标题】:C# "lock" keyword: Why is an object necessary for the syntax?C#“lock”关键字:为什么语法需要对象? 【发布时间】:2014-09-23 22:52:23 【问题描述】:

要将代码标记为关键部分,我们这样做:

Object lockThis = new Object();    
lock (lockThis)
    
     //Critical Section

为什么必须将对象作为锁定语法的一部分?换句话说,为什么这不能一样工作:

lock

   //Critical Section

【问题讨论】:

正如所写,每个lockThis 都会不同,因此不会发生有效的锁定(我希望您的意思是这是一个private readonly,也许是static,字段)。需要对其进行某种范围/锁定。你提议的锁到底是什么:一个通用的东西,一个static自动生成的字段,一个实例自动生成的字段..?这些都有利有弊,强迫你明确地说出锁定对象也是如此。明确地说锁定对象具有清晰的优点,而隐式选项则没有。 您实际上是在问“为什么锁有钥匙?” Servy - 正确,为什么锁有钥匙。蒂姆,好点子。我的意思是 lockThis 是一个私有的静态只读字段。我忘记了。 【参考方案1】:

因为你不只是锁定 - 你锁定了某物(你锁定了一把锁)。

锁定的目的是禁止两个线程直接竞争同一个资源。因此,您将该资源隐藏在任意对象后面。该任意对象充当锁。当一个线程进入临界区时,它会锁定锁,而其他线程无法进入。当线程在临界区完成其工作时,它会解锁并将密钥留给接下来碰巧出现的线程。

如果一个程序有一个资源是竞争访问的候选资源,那么它可能还会有其他这样的资源!但通常这些资源是相互独立的——换句话说,一个线程能够锁定一个特定资源,而另一个线程同时能够锁定另一个资源可能是有意义的,而这两者不会相互干扰。

可能还需要从两个关键部分访问资源。这两个将需要具有相同的锁。如果每个人都有自己的,他们将无法有效地保持资源不受竞争。

显然,我们不只是锁定 - 我们锁定每个特定资源自己的锁定。但是编译器不能静默自动生成任意锁对象,因为它不知道哪些资源应该使用同一个锁来锁定,哪些资源应该有自己的锁。这就是为什么您必须明确声明哪个锁保护哪个代码块(或 )。

请注意,正确使用对象作为锁需要对象是持久的(至少与对应的资源一样持久)。换句话说,您不能在本地范围内创建它,将其存储在本地变量中并在范围退出时将其丢弃,因为这意味着您实际上并没有锁定任何东西。如果您有一个持久对象作为给定资源的锁,则只有一个线程可以进入该部分。如果每次有人尝试进入时都创建一个新的锁定对象,那么任何人都可以随时进入。

【讨论】:

很好的答案,谢谢!虽然这里的每一个回复都让我对“锁定”有了更多的了解,但这是我认为最全面的答案。它涵盖了锁定范围的问题以及需要同时锁定多个关键部分的用例,因此需要相同的“锁定和密钥”。 非常感谢您的解释@Theodoros Chatzigiannakis...这非常有用且易于理解。【参考方案2】:

它需要一些东西来用作锁。

这样两个不同的方法可以共享同一个锁,所以一次只能使用一个。

Object lockThis = new Object();    

void read()

  lock (lockThis)
      
     //Critical Section
  

void write()

  lock (lockThis)
      
     //Critical Section
  

【讨论】:

啊!所以我在考虑是否需要保护一段代码免受多个线程一次执行相同代码的影响。现在使用您的现成和编写示例更有意义。基本上,通过拥有一个键(lockThis),我可以拥有 n 个临界区,这样当一个线程声明“lockThis”上的锁时,所有被“lockThis”锁定的临界区都不能被其他线程访问? 【参考方案3】:

嗯,简单的答案是,这就是指定语言的方式。锁需要有某种对象来锁定。这允许您通过控制此对象的范围和生命周期来控制必须锁定哪些代码。见lock Statement (C# Reference)。

语言的设计者有可能像您建议的那样提供匿名样式的锁,并依赖编译器在幕后生成适当的对象。但是创建的对象应该是静态成员还是实例成员?如果您有多个方法需要在一个类中锁定,它将如何使用?这些都是难题,我敢肯定,语言的设计者根本不觉得包含这样一个结构的好处值得增加复杂性或混乱。

【讨论】:

lock 实际上只是 Monitor 类的语法糖。当然,这只是提出了一个问题“为什么 Monitor 需要一个锁定对象?”我似乎想起了一些描述 Monitor 在内部对 lock 对象所做的事情,但我现在找不到它。 “为什么不直接说lock”的答案与“为什么不直接说lock(this)”的答案相同。 @RobertHarvey 真的。我读到这个问题更多的是关于lock 语法而不是Monitor 类使用的线程同步的实现。

以上是关于C#“lock”关键字:为啥语法需要对象?的主要内容,如果未能解决你的问题,请参考以下文章

C#中lock死锁

Java进击C#——语法之线程同步

C#中Lock的秘密

c#中Lock的秘密

关于 C# 中的 lock 语句的困惑

C#中的lock关键字