2014-07-22 52 views
1

请解释这两种锁定类型之间的区别。多线程:锁定对象类型之间的区别

我有一个List,我想访问线程安全:

var tasks = new List<string>(); 

1.

var locker = new object(); 
lock (locker) 
{ 
    tasks.Add("work 1"); 
} 

2.

lock (tasks) 
{ 
    tasks.Add("work 2"); 
} 

我的想法:

  1. 防止两个不同的线程同时运行锁定的代码块。

但是,如果另一个线程运行不同的方法,它试图访问task - 这种类型的lock不会帮助。

  1. 阻止List<>实例,所以其他方法中的其他线程将被阻塞,直到我解锁tasks

我是对还是错?

+1

请参阅[此问题](http://stackoverflow.com/questions/6891711/difference-between-lockthis-and-a-- lock-on-static-object?rq = 1)和帖子上的链接。 – gunr2171

+0

*您的想法*不正确。没有这样的事情,例如*阻止实例*。 'Lock'关键字是通过* Monitor.Enter *和* Monitor.Exit实现的。请参阅http://stackoverflow.com/questions/4978850/monitor-vs-lock – EZI

回答

2

(2)仅阻止明确调用lock (tasks)的其他代码。通常,只有在知道任务是私人字段时才应该这样做,因此可以在整个班级中执行lock (tasks)意味着锁定列表上的操作。当锁在概念上与访问集合链接并且您不需要担心公开曝光锁时,这可能是一个很好的捷径。尽管如此,你不会得到这个“免费”的东西。它需要被显式使用,就像锁定任何其他对象一样。

+0

我还是不明白...如果两个线程运行不同类中的不同方法,并且都尝试访问静态List <>(来自第三个类),那么提供线程安全性的最佳方式是什么? 1)锁定List对象; 2)锁定专门创建的'var locker = new object()'(不同类的不同储物柜)3)在两种方法中锁定一个通用'locker'。 ? – Andrew

+1

@Andrew试图锁定一个公开可见的静态列表是危险的领域。你可以让他们都同意在执行操作时锁定相同的列表实例,但只需要一个不合作的班级为每个人破坏派对。您可能需要考虑将线程安全的集合访问封装到不同的类中,以使所有类都可以引用,而不是使用静态集合。 –

+1

@Andrew,关于(2),你肯定不想为不同的类使用不同的储物柜,因为它们使用相同的集合并可能会破坏其状态。 –

1

他们做同样的事情。试图修改列表而不锁定同一对象的任何其他代码都会导致潜在的竞争条件。

一个更好的方法可能是将列表封装到另一个获取锁的对象中,然后对基础列表执行任何操作,然后其他任何代码都可以简单地调用封装对象的方法而不必担心获取锁。

+0

所以如果两个选项都相同,最好的方法是什么:锁定专门创建的对象(如'locker')或锁定集合本身? – Andrew

+0

@Andrew如果列表本身和锁柜对象具有相同的范围,则不会有任何区别。但是,如果锁定器对象对其他想要执行线程安全操作的代码不可见,则它将无法获得该锁。 – mclaassen

+0

我还是不明白......如果两个线程运行不同类的方法,并且都尝试访问静态List <>(来自第三类),那么提供线程安全的最佳方式是什么? 1)锁定List对象; 2)锁定专门创建的'var locker = new object()'(不同类的不同储物柜)3)在两种方法中锁定一个通用'locker'。 ? – Andrew

相关问题