none
C# 4.0之前lock为什么不把Monitor.Enter放到try里面呢? RRS feed

  • 问题

  • C# 4.0中的lock语句默认使用的是Monitor.Enter(object, bool),并把Monitor.Enter放到了try语句块的里面,这样可以解决一些死锁问题。

    我想问的是,为什么C# 4.0之前的lock不把Monitor.Enter(object)也放到try里面呢?这样也可以解决一部分死锁问题。但为什么要放在try外面?这么做有什么考虑吗?

    2011年2月18日 6:09

答案

  • C# compiler 的設計者 Eric Lippert 在這裡有解釋各種設計的難處

    http://blogs.msdn.com/b/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx

    The purpose of the lock statement is to help you protect the integrity of a mutable resource that is shared by multiple threads. But suppose an exception is thrown halfway through a mutation of the locked resource. Our implementation of lock does not magically roll back the mutation to its pristine state, and it does not complete the mutation. Rather, control immediately branches to the finally, releasing the lock and allowing every other thread that is patiently waiting to immediately view the messed-up partially mutated state! If that state has privacy, security, or human life and safety implications, the result could be very bad indeed. In that case it is possibly better to deadlock (死锁) the program and protect the messed-up resource by denying access to it entirely. But that's obviously not good either.

    Basically, we all have a difficult choice to make whenever doing multi-threaded programming. We can (1) automatically release locks upon exceptions, exposing inconsistent state and living with the resulting bugs (bad) (2) maintain locks upon exceptions, deadlocking the program (arguably often worse) or (3) carefully implement the bodies of locks that do mutations so that in the event of an exception, the mutated resource is rolled back to a pristine state before the lock is released. (Good, but hard.)

    2011年2月19日 1:02