究竟是什么意思锁定一个对象?

Tho*_*mas 6 c# multithreading locking

尽管我在我的应用程序中使用锁定,但我不明白锁定特定引用类型的确切原因.我认为它只是停止线程,直到{}的内容完成.但我已经读过锁定(这个)很糟糕,如果是公开的 - 为什么?文章解释了它,但我不明白我不知道对象本身被锁定的情况.例如,如果我使用lock(this)并从另一个线程调用其方法怎么办?我以为只有锁下的代码受到保护,否则我将无法访问被锁定的对象?谢谢

Mar*_*ell 8

托管堆上的每个对象都可以用作锁对象,这是一种在线程之间同步访问的方法.

我认为它只是停止线程,直到{}的内容完成.

好吧,lock它会阻止其他线程获取锁,直到锁被释放,这通常是在lock语句结束时(但它也可能是a Monitor.Wait).

lock(this)使用是危险的,因为锁是复杂的,了解究竟哪些线程锁定哪个对象(S),此时是为了避免死锁非常重要; 但是,如果你lock(this)不能控制其他线程 - 这可能(意外地)锁定同一个对象.使用private字段进行锁定要安全得多.

例如,如果你有(在同步列表中):

private IList<T> innerList = ...
public int Count { get { lock(this) { return innerList.Count; } } }
Run Code Online (Sandbox Code Playgroud)

然后不难想象另外一些代码也会引用这个同步列表并锁定它,例如:

SyncList<T> list = ...
lock(list) { // lock for atomicity
    if(!list.Contains(value)) list.Add(value);
}
Run Code Online (Sandbox Code Playgroud)

这是一个潜在的僵局; 如果Count 这样会好得多lock(this),但锁定一个私人对象,即

private readonly object syncLock = new object();
public int Count { get { lock(syncLock) { return innerList.Count; } } }
Run Code Online (Sandbox Code Playgroud)

现在没有这个问题的风险.这里的另一个问题是类似字段的事件和[MethodImpl]原因lock(this).Type出于完全相同的原因,锁定(对于静态方法)同样是危险的.


Jon*_*eet 7

对象本身未锁定.将每个对象视为具有关联的锁(或监视器).当一个线程获得锁定时,没有其他线程可以在没有第一个线程释放它的情况下通过调用Monitor.Exit(这是在lock语句结束时发生的事情)或通过调用来获取它Monitor.Wait.调用Monitor.Enter获取锁的线程将阻塞,直到它可以获取锁.

对象本身根本不受"保护" - 锁定基本上是建议性的.

不锁定"this"的原因是你不知道其他代码对"this"的引用.获得正确的锁定需要您知道线程将在哪些情况下拥有锁定 - 并且您无法知道控制之外的代码是否可以取消锁定.例外情况是,如果您为了共享锁的明确目的而公开引用(如SyncRoot.NET 1.1集合上的属性).