• 锁的封装 读写锁、lock


    最近由于项目上面建议使用读写锁,而去除常见的lock锁。然后就按照需求封装了下锁。以简化锁的使用。但是开发C#的童鞋都知道lock关键字用起太方便了,但是lock关键字不支持超时处理。很无奈,为了实现类似lock的功能。于是通过使用using关键字和IDisposable实现了自己的锁方法

      class Program
        {
            static void Main(string[] args)
            {
                ReadWriteUtilTest();
                MonitorUtilTest();
                Console.ReadLine();
            }
            private static void MonitorUtilTest()
            {
                MonitorUtil util = new MonitorUtil();
                int num = 0;
                for (int index = 0; index < 20; index++)
                {
                    var th = new Thread(new ThreadStart(() =>
                     {
                         Thread.Sleep(100);
                         for (int i = 0; i < 100; i++)
                         {
                             using (util.GetLock("hello"))
                             {
                                 num++;
                                 Console.WriteLine("num={0}", num);
                             }
                         }
                     }));
    
                    th.Start();
                }
            }
    
            private static void ReadWriteUtilTest()
            {
                ReadWriteLockUtil utl = new ReadWriteLockUtil();
                Int32 num = 0;
                for (var i = 0; i < 10; i++)
                {
                    Task.Factory.StartNew(() =>
                    {
                        while (true)
                        {
                            using (utl.GetLock("hello", ReadWriteLockUtil.ReadWriteEnum.Read))
                            {
                                Console.WriteLine("num={0}", num);
                                Thread.Sleep(1000);
                            }
                        }
                    });
                }
                Task.Factory.StartNew(() =>
                {
                    while (true)
                    {
                        using (utl.GetLock("hello", ReadWriteLockUtil.ReadWriteEnum.Write))
                        {
                            num++;
                            Thread.Sleep(5000);
                        }
                        Thread.Sleep(5000);
                    }
                });
            }
        }
    
        /// <summary>
        /// 排他锁工具类
        /// </summary>
        public class MonitorUtil
        {
            /// <summary>
            /// 自定义锁对象
            /// </summary>
            internal class CustMonitor : IDisposable
            {
                /// <summary>
                /// 锁对象
                /// </summary>
                private Object lockObj = null;
    
                /// <summary>
                /// 构造函数
                /// </summary>
                /// <param name="lockObj">锁对象</param>
                public CustMonitor(Object lockObj)
                {
                    this.lockObj = lockObj;
                }
    
                /// <summary>
                /// 锁释放
                /// </summary>
                public void Dispose()
                {
                    try
                    {
                        Monitor.Exit(this.lockObj);
                    }
                    catch
                    {
                        // 当前线程如果没有获取到锁时,则会抛出异常。此处直接吞掉
                    }
                }
            }
    
            /// <summary>
            /// 锁信息
            /// </summary>
            internal class LockInfo
            {
                /// <summary>
                /// 构造函数
                /// </summary>
                /// <param name="lockObj">锁实例</param>
                /// <param name="custMonitor">自定义锁对象</param>
                public LockInfo(Object lockObj, CustMonitor custMonitor)
                {
                    this.CustMonitor = custMonitor;
                    this.LockObj = lockObj;
                }
    
                /// <summary>
                /// 自定义锁对象
                /// </summary>
                public CustMonitor CustMonitor { get; private set; }
    
                /// <summary>
                /// 锁实例
                /// </summary>
                public Object LockObj { get; private set; }
            }
    
            /// <summary>
            /// 锁集合
            /// </summary>
            private ConcurrentDictionary<String, LockInfo> lockObjData = new ConcurrentDictionary<String, LockInfo>();
    
            /// <summary>
            /// lockObjData同步对象
            /// </summary>
            private Object custLockObj = new Object();
    
            /// <summary>
            /// 获取锁对象
            /// </summary>
            /// <param name="lockName">返回锁对象</param>
            /// <param name="waitTime">等待时间(单位:毫秒)</param>
            /// <returns>返回锁对象</returns>
            /// <exception cref="TimeoutException">获取锁对象超时时,抛出此异常</exception>
            public IDisposable GetLock(String lockName, Int32 waitTime = 10)
            {
                // 获取锁对象
                var lockObj = GetLockInfo(lockName);
    
                // 规范等待时间长
                if (waitTime <= 0)
                {
                    // 进入锁
                    Monitor.Enter(lockObj.LockObj);
                }
                else
                {
                    // 进入锁
                    if (Monitor.TryEnter(lockObj.LockObj, waitTime) == false)
                    {
                        return lockObj.CustMonitor;
                        //throw new TimeoutException("等待锁超时");
                    }
                }
    
                return lockObj.CustMonitor;
            }
    
            /// <summary>
            /// 获取锁对象信息
            /// </summary>
            /// <param name="lockName">锁名称</param>
            /// <returns>返回锁对象</returns>
            private LockInfo GetLockInfo(String lockName)
            {
                LockInfo lockObj = null;
    
                // 懒汉方式,先获取一次锁对象
                if (lockObjData.ContainsKey(lockName))
                {
                    lockObj = lockObjData[lockName];
                }
                else
                {
                    lock (custLockObj)
                    {
                        if (lockObjData.ContainsKey(lockName))
                        {
                            lockObj = lockObjData[lockName];
                        }
                        else
                        {
                            // 如果获取不到锁,则创建一个锁对象
    
                            var lockInstance = new Object();
                            lockObj = new LockInfo(lockInstance, new CustMonitor(lockInstance));
    
                            lockObjData[lockName] = lockObj;
                        }
                    }
                }
    
                return lockObj;
            }
        }
    
        /// <summary>
        /// 读写锁工具类
        /// </summary>
        public class ReadWriteLockUtil
        {
            /// <summary>
            /// 自定义锁对象
            /// </summary>
            internal class CustMonitor : IDisposable
            {
                /// <summary>
                /// 获取方式
                /// </summary>
                private ReadWriteEnum getType;
    
                /// <summary>
                /// 锁对象
                /// </summary>
                private ReaderWriterLockSlim lockObj = null;
    
                /// <summary>
                /// 构造函数
                /// </summary>
                /// <param name="lockObj">锁对象</param>
                /// <param name="getType">获取方式</param>
                public CustMonitor(ReaderWriterLockSlim lockObj, ReadWriteEnum getType)
                {
                    this.lockObj = lockObj;
                    this.getType = getType;
                }
    
                /// <summary>
                /// 锁释放
                /// </summary>
                public void Dispose()
                {
                    if (getType == ReadWriteEnum.Read && lockObj.IsReadLockHeld)
                    {
                        lockObj.ExitReadLock();
                    }
                    else if (getType == ReadWriteEnum.Write && lockObj.IsWriteLockHeld)
                    {
                        lockObj.ExitWriteLock();
                    }
                }
            }
    
            /// <summary>
            /// 读写枚举
            /// </summary>
            public enum ReadWriteEnum
            {
                /// <summary>
                ////// </summary>
                Read,
    
                /// <summary>
                ////// </summary>
                Write
            }
    
            /// <summary>
            /// 锁集合
            /// </summary>
            private ConcurrentDictionary<String, ReaderWriterLockSlim> lockObjData = new ConcurrentDictionary<String, ReaderWriterLockSlim>();
    
            /// <summary>
            /// lockObjData同步对象
            /// </summary>
            private Object custLockObj = new Object();
    
            /// <summary>
            /// 获取锁对象
            /// </summary>
            /// <param name="lockName">返回锁对象</param>
            /// <param name="getType">获取方式</param>
            /// <param name="waitTime">等待时间(单位:毫秒),大于0,则等待指定时间,非正数,则死等</param>
            /// <returns>返回锁对象</returns>
            /// <exception cref="TimeoutException">获取锁对象超时时,抛出此异常</exception>
            public IDisposable GetLock(String lockName, ReadWriteEnum getType, Int32 waitTime = 10000)
            {
                // 获取锁对象
                var lockInfo = GetLockInfo(lockName);
    
                // 规范等待时间长
                if (waitTime <= 0)
                {
                    // 进入锁
                    return GetLockByInfiniteWait(lockName, getType);
                }
    
                // 进入锁
                if (getType == ReadWriteEnum.Read)
                {
                    if (lockInfo.IsReadLockHeld || lockInfo.TryEnterReadLock(waitTime))
                    {
                        return new CustMonitor(lockInfo, getType);
                    }
    
                    throw new TimeoutException("等待读锁超时");
                }
                else if (getType == ReadWriteEnum.Write)
                {
                    if (lockInfo.IsWriteLockHeld || lockInfo.TryEnterWriteLock(waitTime))
                    {
                        return new CustMonitor(lockInfo, getType);
                    }
    
                    throw new TimeoutException("等待写锁超时");
                }
    
                return null;
            }
    
            /// <summary>
            /// 获取锁对象,获取过程会死等。直到获取到锁对象
            /// </summary>
            /// <param name="lockName">锁名称</param>
            /// <param name="getType">获取方式</param>
            /// <returns>返回锁对象</returns>
            private IDisposable GetLockByInfiniteWait(String lockName, ReadWriteEnum getType)
            {
                // 获取锁对象
                var lockObj = GetLockInfo(lockName);
    
                // 进入锁
                if (getType == ReadWriteEnum.Read)
                {
                    lockObj.EnterReadLock();
    
                    return new CustMonitor(lockObj, getType);
                }
                else if (getType == ReadWriteEnum.Write)
                {
                    lockObj.EnterWriteLock();
    
                    return new CustMonitor(lockObj, getType);
                }
    
                return null;
            }
    
            /// <summary>
            /// 获取锁对象信息
            /// </summary>
            /// <param name="lockName">锁名称</param>
            /// <returns>返回锁对象</returns>
            private ReaderWriterLockSlim GetLockInfo(String lockName)
            {
                ReaderWriterLockSlim lockObj = null;
    
                // 懒汉方式,先获取一次锁对象
                if (lockObjData.ContainsKey(lockName))
                {
                    lockObj = lockObjData[lockName];
                }
                else
                {
                    lock (custLockObj)
                    {
                        if (lockObjData.ContainsKey(lockName))
                        {
                            lockObj = lockObjData[lockName];
                        }
                        else
                        {
                            // 如果获取不到锁,则创建一个锁对象
                            lockObj = new ReaderWriterLockSlim();
                            lockObjData[lockName] = lockObj;
                        }
                    }
                }
    
                return lockObj;
            }
        }
  • 相关阅读:
    指针数组、数组指针以及二维数组
    jquery的基本动画方法
    jquery面试需要看的基本东西
    bootstrap
    node全栈工程师
    setTimeout 0秒
    随便写的
    Bootstrap2和3的区别
    记忆的代码
    offsetWidth与scrollLeft
  • 原文地址:https://www.cnblogs.com/foreverme/p/5514370.html
Copyright © 2020-2023  润新知