锁的封装 读写锁、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;
        }
    }

 

转载于:https://www.cnblogs.com/foreverme/p/5514370.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis可以通过使用RedLock算法来实现分布式的延期。RedLock是基于多个Redis集群部署的高可用分布式解决方案。在RedLock中,如果master节点宕机期间,可以容忍多个客户端同时持有。因此,如果你的Redis集群是单master的,那么你需要考虑是否可以使用Redis作为分布式。\[2\] 具体来说,你可以使用Redisson库来实现RedLock。Redisson提供了封装了可重入(Reentrant Lock)、公平(Fair Lock)、联(MultiLock)、红(RedLock)、读写锁(ReadWriteLock)、信号量(Semaphore)、可过期性信号量(PermitExpirableSemaphore)、闭(CountDownLatch)等多种的功能。你可以参考Redisson的官方文档来了解具体的使用说明。\[1\] 通过使用RedLock,你可以保证分布式的高可用性和数据的绝对不丢失。这对于存储信息非常重要,因为Redis集群是异步复制的方式,可以容忍一定范围的数据丢失,但是信息是不能丢失的。因此,RedLock通过多个master节点来保证数据的绝对不丢失。\[3\] #### 引用[.reference_title] - *1* *2* [Redis的分布式详解](https://blog.csdn.net/a745233700/article/details/88084219)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [分布式、ZK分布式、Redis分布式](https://blog.csdn.net/weixin_35794878/article/details/122635171)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值