码迷,mamicode.com
首页 > 其他好文 > 详细

读写锁学习(3)——微软源码实现的阅读

时间:2014-11-21 18:21:23      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:blog   io   ar   os   sp   数据   on   div   art   

以下是微软源码,主要看了申请读锁EnterReadLock()、申请写锁EnterWriteLock()、释放读锁ExitReadLock()、释放写锁ExitWriteLock()这四个方法,在下研究了两天,里面有很多细节问题还是了解的不够透彻,表述如有错误希望各位大神能指点一下,主要是通过myLock置0或置1来判断是否可以申请锁资源,通过threadRWCount这个数据结构来统计线程中存在读写锁的数量,这个数据结构通过LockId这个值来标识区分。用readercount和writercount分别统计读写锁的数量,当申请读锁时,如果writercount的值为1则表示存在读锁,写锁申请不成功,进入自旋等待;同理,申请读锁情况类似,从而实现读写锁的互斥。基于这个简单的原理可以写一个简单的读写锁实现方法。

using System;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Security.Permissions;
using System.Threading;

namespace MicrosoftReaderWriterLock
{
    public class ReaderWriterLockSlimer
    {
        private struct TimeoutTracker
        {
            private int m_total;
            private int m_start;
            public int RemainingMilliseconds
            {
                get
                {
                    if (this.m_total == -1 || this.m_total == 0)
                    {
                        return this.m_total;
                    }
                    int num = Environment.TickCount - this.m_start;
                    if (num < 0 || num >= this.m_total)
                    {
                        return 0;
                    }
                    return this.m_total - num;
                }
            }
            //判断是否过期
            public bool IsExpired
            {
                get
                {
                    return this.RemainingMilliseconds == 0;
                }
            }
            public TimeoutTracker(TimeSpan timeout)
            {
                long num = (long)timeout.TotalMilliseconds;
                if (num < -1L || num > 2147483647L)
                {
                    throw new ArgumentOutOfRangeException("timeout");
                }
                this.m_total = (int)num;
                if (this.m_total != -1 && this.m_total != 0)
                {
                    this.m_start = Environment.TickCount;
                    return;
                }
                this.m_start = 0;
            }

            //millsecondsTimeout=-1
            public TimeoutTracker(int millisecondsTimeout)
            {

                if (millisecondsTimeout < -1)
                {
                    throw new ArgumentOutOfRangeException("millisecondsTimeout");
                }
                //m.total=-1,this表当前实例
                this.m_total = millisecondsTimeout;
                if (this.m_total != -1 && this.m_total != 0)
                {
                    this.m_start = Environment.TickCount;
                    return;
                }
                this.m_start = 0;
            }
        }
        private bool fIsReentrant;
        private int myLock;
        private uint numWriteWaiters;
        private uint numReadWaiters;
        private uint numWriteUpgradeWaiters;
        private uint numUpgradeWaiters;
        private bool fNoWaiters;
        private int upgradeLockOwnerId;
        private int writeLockOwnerId;
        private EventWaitHandle writeEvent;
        private EventWaitHandle readEvent;
        private EventWaitHandle upgradeEvent;
        private EventWaitHandle waitUpgradeEvent;
        private long lockID;
        private static ReaderWriterCount t_rwc;
        private bool fUpgradeThreadHoldingRead;
        private uint owners;
        private bool fDisposed;

        public void EnterReadLock()
        {
            this.TryEnterReadLockTest(-1);
        }

        public void EnterWriteLock()
        {
            this.TryEnterWriteLockTest(-1);
        }

        public void ExitReadLock()
        {
            //myLock为0则置1进行下面程序运行,为1则进入自旋锁处理
            this.EnterMyLock();
            ReaderWriterCount threadRWCount = this.GetThreadRWCount(true);
            //读写锁的数量为空
            if (threadRWCount == null || threadRWCount.readercount < 1)
            {
                //myLock = 0
                this.ExitMyLock();
                //找不到相匹配的读锁
                throw new SynchronizationLockException("SynchronizationLockException_MisMatchedRead");
            }
            //可以重写入
            if (this.fIsReentrant)
            {
                if (threadRWCount.readercount > 1)
                {
                    //存在多个读锁时,读锁数量大于1时一点点减少读锁数量,
                    threadRWCount.readercount--;
                    //释放锁资源myLock=0,其他线程可以申请锁
                    this.ExitMyLock();
                    //通知宿主执行即将进入一个区域的代码中的一个线程中止或未处理的异常仅影响当前任务。
                    Thread.EndCriticalRegion();
                    return;
                }
                //允许一个对象被传递给线程在线程启动
                if (Thread.CurrentThread.ManagedThreadId == this.upgradeLockOwnerId)
                {
                    this.fUpgradeThreadHoldingRead = false;
                }
            }
            this.owners -= 1u;
            //减少读锁数
            threadRWCount.readercount--;
            //退出并唤醒适合的等待者
            this.ExitAndWakeUpAppropriateWaiters();
            //执行即将进入一个区域的代码中的一个线程中止或未处理的异常仅影响当前任务。
            Thread.EndCriticalRegion();
        }

        public void ExitWriteLock()
        {
            if (!this.fIsReentrant)
            {
                if (Thread.CurrentThread.ManagedThreadId != this.writeLockOwnerId)
                {
                    //缺少匹配的写锁
                    throw new SynchronizationLockException("SynchronizationLockException_MisMatchedWrite");
                }
                //myLock为0则置1并返回0,表示获得锁资源。为1则返回1,表示没有获得锁资源进入自旋锁
                this.EnterMyLock();
            }
            else
            {
                //myLock为0则置1并返回0,表示获得锁资源。为1则返回1,表示没有获得锁资源进入自旋锁
                this.EnterMyLock();
                ReaderWriterCount threadRWCount = this.GetThreadRWCount(false);
                if (threadRWCount == null)
                {
                    //释放锁资源
                    this.ExitMyLock();
                    //缺少匹配的写锁
                    throw new SynchronizationLockException("SynchronizationLockException_MisMatchedWrite");
                }
                if (threadRWCount.writercount < 1)
                {
                    //释放锁资源
                    this.ExitMyLock();
                    //缺少匹配的写锁
                    throw new SynchronizationLockException("SynchronizationLockException_MisMatchedWrite");
                }
                //写锁数减减
                threadRWCount.writercount--;
                if (threadRWCount.writercount > 0)
                {
                    //释放锁资源
                    this.ExitMyLock();
                    //通知宿主执行将要进入一个代码区域,在该代码区域内线程中止或未经处理的异常仅影响当前任务。
                    Thread.EndCriticalRegion();
                    return;
                }
            }
            this.ClearWriterAcquired();
            this.writeLockOwnerId = -1;
            //退出并唤醒适合的等待者
            this.ExitAndWakeUpAppropriateWaiters();
            //执行即将进入一个区域的代码中的一个线程中止或未处理的异常仅影响当前任务。
            Thread.EndCriticalRegion();
        }

        public bool TryEnterReadLockTest(int millisecondsTimeout)
        {
            return this.TryEnterReadLockTest(new ReaderWriterLockSlimer.TimeoutTracker(millisecondsTimeout));
        }

        public bool TryEnterWriteLockTest(int millisecondsTimeout)
        {
            return this.TryEnterWriteLockTest(new ReaderWriterLockSlimer.TimeoutTracker(millisecondsTimeout));
        }

        private bool TryEnterReadLockTest(ReaderWriterLockSlimer.TimeoutTracker timeout)
        {
            //通知宿主执行将要进入一个代码区域,在该代码区域内线程中止或未经处理的异常的影响可能会危害应用程序域中的其他任务。
            Thread.BeginCriticalRegion();
            bool flag = false;
            try
            {
                flag = this.TryEnterReadLockCore(timeout);
            }
            finally
            {
                if (!flag)
                {
                    //通知宿主执行将要进入一个代码区域,在该代码区域内线程中止或未经处理的异常仅影响当前任务。
                    Thread.EndCriticalRegion();
                }
            }
            return flag;
        }

        private bool TryEnterWriteLockTest(ReaderWriterLockSlimer.TimeoutTracker timeout)
        {
            //通知宿主执行将要进入一个代码区域,在该代码区域内线程中止或未经处理的异常的影响可能会危害应用程序域中的其他任务。
            Thread.BeginCriticalRegion();
            bool flag = false;
            try
            {
                flag = this.TryEnterWriteLockCore(timeout);
            }
            finally
            {
                if (!flag)
                {
                    Thread.EndCriticalRegion();
                }
            }
            return flag;
        }

        private bool TryEnterReadLockCore(ReaderWriterLockSlimer.TimeoutTracker timeout)
        {
            if (this.fDisposed)
            {
                throw new ObjectDisposedException(null);
            }
            ReaderWriterCount readerWriterCount = null;
            //定义managedThreadId表示为托管线程唯一标识的整数
            int managedThreadId = Thread.CurrentThread.ManagedThreadId;
            if (!this.fIsReentrant)
            {
                if (managedThreadId == this.writeLockOwnerId)
                {
                    //不能对已写锁上加读锁
                    throw new LockRecursionException("LockRecursionException_ReadAfterWriteNotAllowed");
                }
                //尝试加锁
                this.EnterMyLock();
                readerWriterCount = this.GetThreadRWCount(false);
                if (readerWriterCount.readercount > 0)
                {
                    this.ExitMyLock();
                    throw new LockRecursionException("LockRecursionException_RecursiveReadNotAllowed");
                }
                if (managedThreadId == this.upgradeLockOwnerId)
                {
                    readerWriterCount.readercount++;
                    this.owners += 1u;
                    this.ExitMyLock();
                    return true;
                }
            }
            else
            {
                this.EnterMyLock();
                readerWriterCount = this.GetThreadRWCount(false);
                if (readerWriterCount.readercount > 0)
                {
                    readerWriterCount.readercount++;
                    this.ExitMyLock();
                    return true;
                }
                if (managedThreadId == this.upgradeLockOwnerId)
                {
                    readerWriterCount.readercount++;
                    this.owners += 1u;
                    this.ExitMyLock();
                    this.fUpgradeThreadHoldingRead = true;
                    return true;
                }
                if (managedThreadId == this.writeLockOwnerId)
                {
                    readerWriterCount.readercount++;
                    this.owners += 1u;
                    this.ExitMyLock();
                    return true;
                }
            }
            bool flag = true;
            int num = 0;
            //当值大于268435454u时才能用以判断
            while (this.owners >= 268435454u)
            {
                if (num < 20)
                {
                    this.ExitMyLock();
                    if (timeout.IsExpired)
                    {
                        return false;
                    }
                    num++;
                    ReaderWriterLockSlimer.SpinWait(num);
                    this.EnterMyLock();
                    if (this.IsRwHashEntryChanged(readerWriterCount))
                    {
                        readerWriterCount = this.GetThreadRWCount(false);
                    }
                }
                else
                {
                    if (this.readEvent == null)
                    {
                        this.LazyCreateEvent(ref this.readEvent, false);
                        if (this.IsRwHashEntryChanged(readerWriterCount))
                        {
                            readerWriterCount = this.GetThreadRWCount(false);
                        }
                    }
                    else
                    {
                        flag = this.WaitOnEvent(this.readEvent, ref this.numReadWaiters, timeout);
                        if (!flag)
                        {
                            return false;
                        }
                        if (this.IsRwHashEntryChanged(readerWriterCount))
                        {
                            readerWriterCount = this.GetThreadRWCount(false);
                        }
                    }
                }
            }
            this.owners += 1u;
            readerWriterCount.readercount++;
            this.ExitMyLock();
            return flag;
        }

        private bool TryEnterWriteLockCore(ReaderWriterLockSlimer.TimeoutTracker timeout)
        {
            if (this.fDisposed)
            {
                throw new ObjectDisposedException(null);
            }
            int managedThreadId = Thread.CurrentThread.ManagedThreadId;
            bool flag = false;
            ReaderWriterCount threadRWCount;
            if (!this.fIsReentrant)
            {
                if (managedThreadId == this.writeLockOwnerId)
                {
                    throw new LockRecursionException("LockRecursionException_RecursiveWriteNotAllowed");
                }
                if (managedThreadId == this.upgradeLockOwnerId)
                {
                    flag = true;
                }
                this.EnterMyLock();
                threadRWCount = this.GetThreadRWCount(true);
                if (threadRWCount != null && threadRWCount.readercount > 0)
                {
                    this.ExitMyLock();
                    throw new LockRecursionException("LockRecursionException_WriteAfterReadNotAllowed");
                }
            }
            else
            {
                this.EnterMyLock();
                threadRWCount = this.GetThreadRWCount(false);
                if (managedThreadId == this.writeLockOwnerId)
                {
                    threadRWCount.writercount++;
                    this.ExitMyLock();
                    return true;
                }
                if (managedThreadId == this.upgradeLockOwnerId)
                {
                    flag = true;
                }
                else
                {
                    if (threadRWCount.readercount > 0)
                    {
                        this.ExitMyLock();
                        throw new LockRecursionException("LockRecursionException_WriteAfterReadNotAllowed");
                    }
                }
            }
            int num = 0;
            while (!this.IsWriterAcquired())
            {
                if (flag)
                {
                    uint numReaders = this.GetNumReaders();
                    if (numReaders == 1u)
                    {
                        this.SetWriterAcquired();
                    }
                    else
                    {
                        if (numReaders != 2u || threadRWCount == null)
                        {
                            goto IL_131;
                        }
                        if (this.IsRwHashEntryChanged(threadRWCount))
                        {
                            threadRWCount = this.GetThreadRWCount(false);
                        }
                        if (threadRWCount.readercount <= 0)
                        {
                            goto IL_131;
                        }
                        this.SetWriterAcquired();
                    }
                IL_1CF:
                    if (this.fIsReentrant)
                    {
                        if (this.IsRwHashEntryChanged(threadRWCount))
                        {
                            threadRWCount = this.GetThreadRWCount(false);
                        }
                        threadRWCount.writercount++;
                    }
                    this.ExitMyLock();
                    this.writeLockOwnerId = managedThreadId;
                    return true;
                }
            IL_131:
                if (num < 20)
                {
                    this.ExitMyLock();
                    if (timeout.IsExpired)
                    {
                        return false;
                    }
                    num++;
                    ReaderWriterLockSlimer.SpinWait(num);
                    this.EnterMyLock();
                }
                else
                {
                    if (flag)
                    {
                        if (this.waitUpgradeEvent == null)
                        {
                            this.LazyCreateEvent(ref this.waitUpgradeEvent, true);
                        }
                        else
                        {
                            if (!this.WaitOnEvent(this.waitUpgradeEvent, ref this.numWriteUpgradeWaiters, timeout))
                            {
                                return false;
                            }
                        }
                    }
                    else
                    {
                        if (this.writeEvent == null)
                        {
                            this.LazyCreateEvent(ref this.writeEvent, true);
                        }
                        else
                        {
                            if (!this.WaitOnEvent(this.writeEvent, ref this.numWriteWaiters, timeout))
                            {
                                return false;
                            }
                        }
                    }
                }
            }
            this.SetWriterAcquired();
            goto IL_1CF;
            //return true;
        }

        internal class ReaderWriterCount
        {
            public long lockID;
            public int readercount;
            public int writercount;
            public int upgradecount;
            public ReaderWriterCount next;
        }
        private void EnterMyLock()
        {
            //myLock为0则置1并返回0,表示获得锁资源。为1则返回1,表示没有获得锁资源
            if (Interlocked.CompareExchange(ref this.myLock, 1, 0) != 0)
            {
                //进入自旋锁
                this.EnterMyLockSpin();
            }
        }

        private ReaderWriterCount GetThreadRWCount(bool dontAllocate)
        {
            ReaderWriterCount next = ReaderWriterLockSlimer.t_rwc;
            ReaderWriterCount readerWriterCount = null;
            while (next != null)
            {
                if (next.lockID == this.lockID)
                {
                    return next;
                }
                //
                if (!dontAllocate && readerWriterCount == null && ReaderWriterLockSlimer.IsRWEntryEmpty(next))
                {
                    readerWriterCount = next;
                }
                next = next.next;
            }

            if (dontAllocate)
            {
                return null;
            }
            if (readerWriterCount == null)
            {
                readerWriterCount = new ReaderWriterCount();
                readerWriterCount.next = ReaderWriterLockSlimer.t_rwc;
                ReaderWriterLockSlimer.t_rwc = readerWriterCount;
            }

            readerWriterCount.lockID = this.lockID;
            return readerWriterCount;
        }

        private void ExitMyLock()
        {
            this.myLock = 0;
        }

        private static void SpinWait(int SpinCount)
        {
            if (SpinCount < 5 && Environment.ProcessorCount > 1)
            {
                Thread.SpinWait(20 * SpinCount);
                return;
            }
            if (SpinCount < 17)
            {
                Thread.Sleep(0);
                return;
            }
            Thread.Sleep(1);
        }

        private bool IsRwHashEntryChanged(ReaderWriterCount lrwc)
        {
            return lrwc.lockID != this.lockID;
        }

        private void LazyCreateEvent(ref EventWaitHandle waitEvent, bool makeAutoResetEvent)
        {
            this.ExitMyLock();
            EventWaitHandle eventWaitHandle;
            if (makeAutoResetEvent)
            {
                eventWaitHandle = new AutoResetEvent(false);
            }
            else
            {
                eventWaitHandle = new ManualResetEvent(false);
            }
            this.EnterMyLock();
            if (waitEvent == null)
            {
                waitEvent = eventWaitHandle;
                return;
            }
            eventWaitHandle.Close();
        }


        private bool WaitOnEvent(EventWaitHandle waitEvent, ref uint numWaiters, ReaderWriterLockSlimer.TimeoutTracker timeout)
        {
            waitEvent.Reset();
            numWaiters += 1u;
            this.fNoWaiters = false;
            if (this.numWriteWaiters == 1u)
            {
                this.SetWritersWaiting();
            }
            if (this.numWriteUpgradeWaiters == 1u)
            {
                this.SetUpgraderWaiting();
            }
            bool flag = false;
            this.ExitMyLock();
            try
            {
                flag = waitEvent.WaitOne(timeout.RemainingMilliseconds, false);
            }
            finally
            {
                this.EnterMyLock();
                numWaiters -= 1u;
                if (this.numWriteWaiters == 0u && this.numWriteUpgradeWaiters == 0u && this.numUpgradeWaiters == 0u && this.numReadWaiters == 0u)
                {
                    this.fNoWaiters = true;
                }
                if (this.numWriteWaiters == 0u)
                {
                    this.ClearWritersWaiting();
                }
                if (this.numWriteUpgradeWaiters == 0u)
                {
                    this.ClearUpgraderWaiting();
                }
                if (!flag)
                {
                    this.ExitMyLock();
                }
            }
            return flag;
        }
        private void SetWritersWaiting()
        {
            //第32位置1
            this.owners |= 1073741824u;
        }

        private void SetUpgraderWaiting()
        {
            //第30位置1
            this.owners |= 536870912u;
        }
        private void ClearWritersWaiting()
        {
            //第31位置0
            this.owners &= 3221225471u;
        }
        private void ClearUpgraderWaiting()
        {
            //第30位置0
            this.owners &= 3758096383u;
        }

        //进入自旋锁处理
        private void EnterMyLockSpin()
        {
            //初始化处理器数
            int processorCount = Environment.ProcessorCount;
            //num用于统计请求次数,10次请求以内进入自旋等待,10次到15次之间不断的请求5次,之后每隔1ms请求一次,直到myLock为0即获得锁资源跳出循环
            int num = 0;
            while (true)
            {
                //num小于10且处理器数量大于1
                if (num < 10 && processorCount > 1)
                {
                    //旋转等待20 * (num + 1)毫秒
                    Thread.SpinWait(20 * (num + 1));
                }
                else
                {
                    if (num < 15)
                    {
                        Thread.Sleep(0);
                    }
                    else
                    {
                        Thread.Sleep(1);
                    }
                }
                //myLock为0即获得锁资源跳出循环
                if (this.myLock == 0 && Interlocked.CompareExchange(ref this.myLock, 1, 0) == 0)
                {
                    break;
                }
                num++;
            }
        }
        //判断ReaderWriterCount是否为空
        private static bool IsRWEntryEmpty(ReaderWriterCount rwc)
        {
            return rwc.lockID == 0L || (rwc.readercount == 0 && rwc.writercount == 0 && rwc.upgradecount == 0);
        }


        private bool IsWriterAcquired()
        {
            //owers=1011  1111111111111111111111111111 为写 
            return (this.owners & 3221225471u) == 0u;
        }

        private uint GetNumReaders()
        {
            //获得所有低位
            return this.owners & 268435455u;
        }

        private void SetWriterAcquired()
        {
            //第32位置1
            this.owners |= 2147483648u;
        }

        //退出并唤醒合适的等待者
        private void ExitAndWakeUpAppropriateWaiters()
        {
            //如果有等待者
            if (this.fNoWaiters)
            {
                //myLock置0表示锁资源可以被调用
                this.ExitMyLock();
                return;
            }
            this.ExitAndWakeUpAppropriateWaitersPreferringWriters();
        }

        private void ExitAndWakeUpAppropriateWaitersPreferringWriters()
        {
            bool flag = false;
            bool flag2 = false;
            uint numReaders = this.GetNumReaders();
            if (this.fIsReentrant && this.numWriteUpgradeWaiters > 0u && this.fUpgradeThreadHoldingRead && numReaders == 2u)
            {
                this.ExitMyLock();
                this.waitUpgradeEvent.Set();
                return;
            }
            if (numReaders == 1u && this.numWriteUpgradeWaiters > 0u)
            {
                this.ExitMyLock();
                this.waitUpgradeEvent.Set();
                return;
            }
            if (numReaders == 0u && this.numWriteWaiters > 0u)
            {
                this.ExitMyLock();
                this.writeEvent.Set();
                return;
            }
            if (numReaders >= 0u)
            {
                if (this.numReadWaiters == 0u && this.numUpgradeWaiters == 0u)
                {
                    this.ExitMyLock();
                    return;
                }
                if (this.numReadWaiters != 0u)
                {
                    flag2 = true;
                }
                if (this.numUpgradeWaiters != 0u && this.upgradeLockOwnerId == -1)
                {
                    flag = true;
                }
                this.ExitMyLock();
                if (flag2)
                {
                    this.readEvent.Set();
                }
                if (flag)
                {
                    this.upgradeEvent.Set();
                    return;
                }
            }
            else
            {
                this.ExitMyLock();
            }
        }

        private void ClearWriterAcquired()
        {
            //第32位置0
            this.owners &= 2147483647u;
        }
    }
}

 

读写锁学习(3)——微软源码实现的阅读

标签:blog   io   ar   os   sp   数据   on   div   art   

原文地址:http://www.cnblogs.com/Freedom0619/p/4113461.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!