首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Silverlight ReaderWriterLock实现好/坏?

Silverlight ReaderWriterLock实现好/坏?
EN

Stack Overflow用户
提问于 2009-03-04 22:32:00
回答 3查看 3.1K关注 0票数 3

我有一个简单的(没有升级或超时) ReaderWriterLock的adopted实现,我想知道任何有合适的专业知识的人都可以验证它是好是坏的设计。对我来说,它看起来很好,它的工作就像广告宣传的那样,但我对多线程代码的经验有限。

代码语言:javascript
复制
public sealed class ReaderWriterLock
{
    private readonly object syncRoot = new object();    // Internal lock.
    private int i = 0;                                  // 0 or greater means readers can pass; -1 is active writer.
    private int readWaiters = 0;                        // Readers waiting for writer to exit.
    private int writeWaiters = 0;                       // Writers waiting for writer lock.
    private ConditionVariable conditionVar;             // Condition variable.

    public ReaderWriterLock()
    {
        conditionVar = new ConditionVariable(syncRoot);
    }

    /// <summary>
    /// Gets a value indicating if a reader lock is held.
    /// </summary>
    public bool IsReaderLockHeld
    {
        get
        {
            lock ( syncRoot )
            {
                if ( i > 0 )
                    return true;
                return false;
            }
        }
    }

    /// <summary>
    /// Gets a value indicating if the writer lock is held.
    /// </summary>
    public bool IsWriterLockHeld
    {
        get
        {
            lock ( syncRoot )
            {
                if ( i < 0 )
                    return true;
                return false;
            }
        }
    }

    /// <summary>
    /// Aquires the writer lock.
    /// </summary>
    public void AcquireWriterLock()
    {
        lock ( syncRoot )
        {
            writeWaiters++;
            while ( i != 0 )
                conditionVar.Wait();      // Wait until existing writer frees the lock.
            writeWaiters--;
            i = -1;             // Thread has writer lock.
        }
    }

    /// <summary>
    /// Aquires a reader lock.
    /// </summary>
    public void AcquireReaderLock()
    {
        lock ( syncRoot )
        {
            readWaiters++;
            // Defer to a writer (one time only) if one is waiting to prevent writer starvation.
            if ( writeWaiters > 0 )
            {
                conditionVar.Pulse();
                Monitor.Wait(syncRoot);
            }
            while ( i < 0 )
                Monitor.Wait(syncRoot);
            readWaiters--;
            i++;
        }
    }

    /// <summary>
    /// Releases the writer lock.
    /// </summary>
    public void ReleaseWriterLock()
    {
        bool doPulse = false;
        lock ( syncRoot )
        {
            i = 0;
            // Decide if we pulse a writer or readers.
            if ( readWaiters > 0 )
            {
                Monitor.PulseAll(syncRoot); // If multiple readers waiting, pulse them all.
            }
            else
            {
                doPulse = true;
            }
        }
        if ( doPulse )
            conditionVar.Pulse();                     // Pulse one writer if one waiting.
    }

    /// <summary>
    /// Releases a reader lock.
    /// </summary>
    public void ReleaseReaderLock()
    {
        bool doPulse = false;
        lock ( syncRoot )
        {
            i--;
            if ( i == 0 )
                doPulse = true;
        }
        if ( doPulse )
            conditionVar.Pulse();                     // Pulse one writer if one waiting.
    }

    /// <summary>
    /// Condition Variable (CV) class.
    /// </summary>
    public class ConditionVariable
    {
        private readonly object syncLock = new object(); // Internal lock.
        private readonly object m;                       // The lock associated with this CV.

        public ConditionVariable(object m)
        {
            lock (syncLock)
            {
                this.m = m;
            }
        }

        public void Wait()
        {
            bool enter = false;
            try
            {
                lock (syncLock)
                {
                    Monitor.Exit(m);
                    enter = true;
                    Monitor.Wait(syncLock);
                }
            }
            finally
            {
                if (enter)
                    Monitor.Enter(m);
            }
        }

        public void Pulse()
        {
            lock (syncLock)
            {
                Monitor.Pulse(syncLock);
            }
        }

        public void PulseAll()
        {
            lock (syncLock)
            {
                Monitor.PulseAll(syncLock);
            }
        }

    }

} 

如果它是好的,它可能对其他人也有帮助,因为Silverlight目前缺乏读写器类型的锁。谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-03-04 23:18:12

我将深入解释Vance Morrison's ReaderWriterLock (在.NET 3.5中成为ReaderWriterLockSlim ) on my blog (深入到x86级别)。这可能会对你的设计有所帮助,尤其是理解事物是如何工作的。

票数 4
EN

Stack Overflow用户

发布于 2009-03-04 22:40:50

您的IsReadorLockHeld和IsWriterLockHeld方法在概念层面上都存在缺陷。虽然可以确定在给定的时间点是否持有特定的锁,但如果没有此信息,则绝对无法安全地执行任何操作,除非您继续持有该锁(而不是代码中的情况)。

这些方法应该更准确地命名为WasReadLockHeldInThePast和WasWriterLockHeldInThePast。一旦您将这些方法重命名为它们所做的事情的更准确的表示形式,就会变得更加清楚,它们并不是很有用。

票数 1
EN

Stack Overflow用户

发布于 2009-03-04 23:11:20

这个类对我来说似乎更简单,并且提供了相同的功能。它的性能可能会稍差一些,因为它总是使用PulsesAll(),但是它的逻辑要简单得多,我怀疑它的性能是否有那么好。

代码语言:javascript
复制
public sealed class ReaderWriterLock()
{
    private readonly object internalLock = new object();
    private int activeReaders = 0;
    private bool activeWriter = false;

    public void AcquireReaderLock()
    {
        lock (internalLock)
        {
            while (activeWriter)
                Monitor.Wait(internalLock);
            ++activeReaders;
        }
    }

    public void ReleaseReaderLock()
    {
        lock (internalLock)
        {
            // if activeReaders <= 0 do some error handling
            --activeReaders;
            Monitor.PulseAll(internalLock);
        }
    }

    public void AcquireWriterLock()
    {
        lock (internalLock)
        {
            // first wait for any writers to clear 
            // This assumes writers have a higher priority than readers
            // as it will force the readers to wait until all writers are done.
            // you can change the conditionals in here to change that behavior.
            while (activeWriter)
                Monitor.Wait(internalLock);

            // There are no more writers, set this to true to block further readers from acquiring the lock
            activeWriter = true;

            // Now wait till all readers have completed.
            while (activeReaders > 0)
                Monitor.Wait(internalLock);

            // The writer now has the lock
        }
    }

    public void ReleaseWriterLock()
    {
        lock (internalLock)
        {
            // if activeWriter != true handle the error
            activeWriter = false;
            Monitor.PulseAll(internalLock);
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/612765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档