2009-04-27 70 views
1

我最近被一位刚刚开始使用线程的朋友问到,纯粹是为了锁定目的还是仅仅锁定您引用的对象而使用次级对象。我不得不承认我不知道,谁能告诉我?我会尝试与一对夫妇的代码片段演示:锁定指定对象和锁定辅助对象有什么区别?

第一种方法:

List<string> data = new List<string>(); 
object datalock = new object(); 

void main() 
{ 
    lock(datalock) 
    { 
     if (data.contains("SomeSearchString")) 
     { 
      //Do something with the data and then remove it 
     } 
    } 
} 

方法二:

List<string> data = new List<string>(); 

void main() 
{ 
    lock(data) 
    { 
     if (data.contains("SomeSearchString")) 
     { 
      //Do something with the data and then remove it 
     } 
    } 
} 

是否有显著差异或者是这个到个人编码风格?如果存在显着差异,任何人都可以解释它是什么?

我确实遇到过另一个问题[Difference between lock(locker) and lock(variable_which_I_am_using)],其中的答案暗示这两个都是等价的,但如果是这样的话,哪个最好用,为什么?

我见过很多遍布网络的例子,我倾向于使用第一种方法作为个人选择的问题,但我想知道使用第二种方法的优点是什么。

回答

5

最大的区别是,第二个对象,只有你的代码知道有来自其他代码(不是你的)锁定对意想不到的后果(死锁,脉冲/等待陷阱等)没有风险主要对象(通常可用于其他代码)。

IMO,也许CLR团队会做的更好的明确Lock类型 - 或者Monitor应该已经无静电等

+0

我只是在输入那个... 我要添加的唯一东西是锁定主对象确实允许子类知道他们正在做什么来参与超类锁定策略,这会提供稍微更大的灵活性 - 但面临不知道自己在做什么的消费者可能导致更多问题的风险。 – 2009-04-27 22:16:56

1

最重要的一点已涵盖马克,但我更喜欢第一种模式,因为它还打开了为读写锁定分隔对象的范围,或者可能对您的特定用途有用的任何其他级别的粒度。

+0

我想它也允许目标对象的子方法在锁被放置时仍然被访问,而不必等待锁被释放。 – BenAlabaster 2009-04-27 22:27:20

0

从根本上说,没有区别。如果所有线程不安全操作锁定在同一个对象上,则没有区别。然而,从实施的角度来看,可能会有差异。如果其他线程需要访问需要独占锁定的对象,则必须确保使该同步对象可用并清除哪个对象需要锁定。

另一方面,在某些情况下,您可能实际上将值分配给锁块内的不同内容。在这种情况下,你显然需要锁定一个不相关的对象。

归结到一点,无论是个人喜好和可维护性(被锁定需要第二个对象,一个坏主意,或者两者都不对?)

0

使用不同的对象锁定允许多个同步的粒度和性能。如果您锁定同一个对象,则一个操作可能会不必要地阻塞另一个对象。如果你使用lock(this),所有的并发操作都必须等到拥有该锁的那个操作释放它。但是,这可能不是必需的,因为某些操作可能不会访问相同的资源。所以你不必要地锁定它们,从而伤害到性能。相反,对不同的共享资源组使用不同的同步对象,并让您的操作使用相应的锁来访问他们需要访问的资源。