没有休假的最佳做法是打开锁

时间:2014-04-26 02:02:40

标签: c# .net multithreading thread-safety readerwriterlockslim

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();
    }
}

2 个答案:

答案 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。你应该试着让你的锁体(即你拿着锁时做的任何事情)尽可能短而简单,以减少抛出异常的机会。