Albahari Threading section about ReaderWriterLockSlim显示了这个储物柜的用法。但是没有任何尝试捕获,最后阻止特殊情况。
为什么他没有使用异常处理来保留未打开的锁?在下面的示例中,如果DivideBy参数为0,则写锁定保持打开状态。
所以他试着简单地显示用法不使示例复杂化?如果是这样,处理这个问题的最佳做法是什么?如果持有,我们应该总是使用finally块进行退出锁定?
public class Divide
{
static int x = 1000;
static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
public void DivideBy(int divide)
{
locker.EnterWriteLock();
x = x / divide;
locker.ExitWriteLock();
}
}
答案 0 :(得分:3)
这是我处理这个问题的个人模式。我更喜欢使用using(IDisposable)
,因为我发现单个使用块与try finally块的错误范围要小得多。
public class Divide
{
static int x = 1000;
static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
public void DivideBy(int divide)
{
using(locker.DisposableWriteLock())
{
x = x / divide;
}
}
}
public static class ReaderWriterLockSlimHelper
{
public static IDisposable DisposableWriteLock(this ReaderWriterLockSlim readWriteLock)
{
readWriteLock.EnterWriteLock();
return new LockContext(readWriteLock.ExitWriteLock);
}
private class LockContext : IDisposable
{
private Action _disposeContext;
private bool _isDiposed;
public LockContext(Action diposeContext)
{
_disposeContext = disposeContext;
}
public void Dispose()
{
if(_isDiposed)
return;
_disposeContext();
_isDiposed = true;
}
}
}
答案 1 :(得分:2)
典型的习语是使用try ... finally:
public void DivideBy(int divide)
{
locker.EnterWriteLock();
try
{
x = x / divide;
}
finally
{
locker.ExitWriteLock();
}
}
这将确保在发生异常时释放锁定。但是,请留意Eric Lippert的Locks and exceptions do not mix。你应该试着让你的锁体(即你拿着锁时做的任何事情)尽可能短而简单,以减少抛出异常的机会。