2012-03-30 18 views
16

最近,我看到了一个网站,这个代码,我的问题是:多线程时锁定单个布尔变量?

 private bool mbTestFinished = false; 

     private bool IsFinished() 
     { 
      lock(mLock) 
      { 
       return mbTestFinished; 
      } 
     } 

     internal void SetFinished() 
     { 
      lock(mLock) 
      { 
       mbTestFinished = true; 
      } 
     } 

在多线程环境中,真的有必要锁定访问mbTestFinished

+6

它是确保它不是CPU缓存读取的最可证明的机制(在线程之间不会很好地工作) - volatile也可以工作,但是由于太复杂的原因(这不是*意图*'volatile',而是:副作用) – 2012-03-30 09:12:54

+4

@MarcGravell我一直认为_was_是volatile的意图;你有可能放弃解释什么是好的链接吗? – 2012-03-30 09:21:16

+1

@romkyns:这[回答](http://stackoverflow.com/a/4103879/158779)提供了一些见解。 – 2012-03-30 14:54:01

回答

9

是的,它是必要的。 .Net环境使用一些优化,有时如果频繁访问内存位置,则数据将移入CPU寄存器。因此,在这种情况下,如果mbTestFinished在CPU寄存器中,则读取它的线程可能会得到错误的值。因此,使用易失性密钥可确保对该变量的所有访问均在内存位置完成,而不是在寄存器中完成。另一方面,我不知道这种发生的频率。这可能发生在一个非常低的频率。

9

在我看来,没有,这个锁是多余这里,有两个原因:

  1. 布尔变量不能导致分配撕裂样long例如,因此锁定是没有必要的。
  2. 要解决可见性问题volatile就够了。确实,lock引入了隐式栅栏,但由于lock对于原子性不是必需的,因此volatile就足够了。
+0

假设显示的代码是使用锁的* only *事物,这是真的。如果有其他地方发生'mLock',则转换为'volatile'可能会破坏事物。 – 2012-03-30 09:28:57

+0

@romkyns:是的,我假设这是一个独立的场景。 – Tudor 2012-03-30 09:29:45

4

如果m锁是ONLY为变量mbTestFinished,那么这是一个有点矫枉过正。相反,您可以使用易失性联锁,因为两者都是用户模式构造用于线程同步。 锁定(或监视器)是杂交构建,在某种意义上说,它是公优化,以避免从/向内核模式尽可能过境。本书“CLR via C#”对这些概念进行了深入的讨论。