Can Monitor.Enter throw an exception?

2019-05-02 01:11发布

Can Monitor.Enter throw any exception. I am doing a code review and find that Monitor.Enter is before try block. Do you see any issues with in?

Monitor.Enter(...)
try
{
    ...
}
finally
{
    Monitor.Exit(..)
}

4条回答
贼婆χ
2楼-- · 2019-05-02 02:06

Hans Passant's comment is of course correct. If Monitor.Enter throws before the lock is taken then you do not want the finally to run. If it throws after the lock is taken and after the try is entered, then the lock is released. (More on this later.) But if the throw happens after the lock is taken but before the try is entered, then the lock will never be cleaned up.

This is a rare but possible situation.

In C# 4 we changed the codegen of the lock statement so that the monitor enter is inside the try. This ensures that the lock is always released if something throws after the lock is taken. However, note that this might still be wrong. If something throws after the lock is taken then whatever non-atomic mutation the lock is protecting might be half-completed, and the finally block then unlocks the lock and allows access to the inconsistent state! The fundamental problem here is that you shouldn't be throwing inside a lock in the first place.

See my article about the issue for more discussion.

查看更多
一夜七次
3楼-- · 2019-05-02 02:13

Monitor.Enter can throw at least the following exceptions

  • ArgumentNullException of the parameter is null
  • ThreadInterruptedException if the thread doing the Enter has it's Interrupt method invoked.
查看更多
再贱就再见
4楼-- · 2019-05-02 02:14

If it acquires the lock, then no.

But an exception might be thrown between the Monitor.Enter and the try block.

The recommended method is the new Enter method, new in .NET 4:

public static void Enter( obj, ref bool lockTaken )
查看更多
姐就是有狂的资本
5楼-- · 2019-05-02 02:15

This is the correct pattern, whether Enter() throws (can throw) or not.

Only after the call to Enter() succeeds your code is under the responsibility to call Exit().

Suppose the call to Enter() fails. Then calling the corresponding Exit() is simply incorrect, it will make matters worse. So Enter() has to be outside (before) the try block.

查看更多
登录 后发表回答