• c#自定义业务锁


    我们有这样的使用场景,某个订单在修改信息的时候,其他人不能修改相关的信息,比如不能做支付,不能退单等等,那么我们可以根据单号进行加锁,多Monitor做了如下扩展

    定义接口

    //// 文件名称:ILockExt.cs
    //// 创建日期:2018-06-07 10:44:39
    // 功能描述:自定义锁接口
    //
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.ConstrainedExecution;
    using System.Text;
    
    namespace Km.Utils.Helpers
    {
        /// <summary>
        /// 功能描述:自定义锁接口
        ////// 创建日期:2018-06-07 10:41:47
        ////// </summary>
        public interface ILockExt : IDisposable
        {
            /// <summary>
            /// 功能描述:在指定对象上获取排他锁。
            ////// 创建日期:2018-06-07 10:25:29
            ////// </summary>
            /// <param name="obj">在其上获取监视器锁的对象</param>
            void Enter(object obj);
    
            /// <summary>
            /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 10:27:21
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为true</param>
            void Enter(object obj, ref bool lockTaken);
    
            /// <summary>
            /// 功能描述:释放指定对象上的排他锁
            ////// 创建日期:2018-06-07 10:36:51
            ////// </summary>
            /// <param name="obj">在其上释放锁的对象</param>
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            void Exit(object obj);
    
            /// <summary>
            /// 功能描述:通知等待队列中的线程锁定对象状态的更改。
            ////// 创建日期:2018-06-07 10:37:15
            ////// </summary>
            /// <param name="obj">线程正在等待的对象</param>
            void Pulse(object obj);
    
            /// <summary>
            /// 功能描述:通知所有的等待线程对象状态的更改。
            ////// 创建日期:2018-06-07 10:37:40
            ////// </summary>
            /// <param name="obj">发送脉冲的对象</param>
            void PulseAll(object obj);
    
            /// <summary>
            /// 功能描述:尝试获取指定对象的排他锁
            ////// 创建日期:2018-06-07 10:37:55
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象。</param>
            /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
            bool TryEnter(object obj);
    
            /// <summary>
            /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:38:11
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
            /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
            bool TryEnter(object obj, int millisecondsTimeout);
    
            /// <summary>
            /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:38:34
            ////// </summary>
            /// <param name="obj">obj</param>
            /// <param name="lockTaken">lockTaken</param>
            void TryEnter(object obj, ref bool lockTaken);
    
            /// <summary>
            /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:39:28
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="timeout">System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
            /// <returns>如果当前线程在不阻止的情况下获取该锁,则为 true;否则为 false</returns>
            bool TryEnter(object obj, TimeSpan timeout);
    
            /// <summary>
            /// 功能描述:在指定的毫秒数中,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁
            ////// 创建日期:2018-06-07 10:40:54
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
            void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken);
    
            /// <summary>
            /// 功能描述:在指定的一段时间内,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 11:12:21
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="timeout">用于等待锁的时间。值为 -1 毫秒表示指定无限期等待</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
            void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken);
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。
            ////// 创建日期:2018-06-07 11:12:45
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <returns> 如果调用由于调用方重新获取了指定对象的锁而返回,则为 true。如果未重新获取该锁,则此方法不会返回。</returns>
            bool Wait(object obj);
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
            ////// 创建日期:2018-06-07 11:13:13
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            bool Wait(object obj, int millisecondsTimeout);
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
            ////// 创建日期:2018-06-07 11:13:35
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量。</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            bool Wait(object obj, TimeSpan timeout);
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。此方法还指定是否在等待之前退出上下文的同步域(如果处于同步上下文中的话)然后重新获取该同步域。
            ////// 创建日期:2018-06-07 11:14:02
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
            /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            bool Wait(object obj, int millisecondsTimeout, bool exitContext);
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。可以在等待之前退出同步上下文的同步域,随后重新获取该域。
            ////// 创建日期:2018-06-07 11:14:34
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量</param>
            /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            bool Wait(object obj, TimeSpan timeout, bool exitContext);
    
    
    
            /// <summary>
            /// 功能描述:在指定对象上获取排他锁
            ////// 创建日期:2018-06-07 10:09:25
            ////// </summary>
            /// <param name="obj">在其上获取监视器锁的对象</param>     
            /// <returns>ILockExt对象</returns>
            ILockExt EnterLock(object obj);
            /// <summary>
            /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 10:10:02
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。Note如果没有发生异常,则此方法的输出始终为true</param>
            /// <returns>ILockExt对象</returns>
            ILockExt EnterLock(object obj, ref bool lockTaken);
            /// <summary>
            /// 功能描述:尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 10:17:29
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
            /// <returns>返回值</returns>
            ILockExt TryEnterLock(object obj, ref bool lockTaken);
            /// <summary>
            /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:14:36
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
            /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
            /// <returns>ILockExt对象</returns>
            ILockExt TryEnterLock(object obj, int millisecondsTimeout, ref bool lockTaken);
            /// <summary>
            /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:15:50
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="timeout"> System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
            /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
            /// <returns>ILockExt对象</returns>
            ILockExt TryEnterLock(object obj, TimeSpan timeout, ref bool lockTaken);
        }
    }
    View Code

    定义基类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace Km.Utils.Helpers
    {
        /// <summary>
        /// 功能描述:自定义锁
        ////// 创建日期:2018-06-07 10:49:26
        ////// </summary>
        public class LockExt : ILockExt
        {
            private static Dictionary<int, string> m_lstLocks = new Dictionary<int, string>();
            /// <summary>
            /// 获取一个新实例
            /// </summary>
            public static ILockExt Instance
            {
                get
                {
                    return new LockExt();
                }
            }
            /// <summary>
            /// 字符串锁类型格式化 by beck.huang 2018-06-07 11:00:25
            /// </summary>
            public string LockFormate
            {
                get;
                set;
            }
            //锁对象
            private int objLockKey;
    
            #region 构造函数
            /// <summary>
            /// 功能描述:构造函数
            ////// 创建日期:2018-06-07 10:49:46
            ////// </summary>
            public LockExt()
            {
    
            }
            /// <summary>
            /// 功能描述:执行与释放或重置非托管资源相关的应用程序定义的任务。
            ////// 创建日期:2018-06-07 10:49:18
            ////// </summary>
            public void Dispose()
            {
                if (objLockKey != 0 && m_lstLocks.ContainsKey(objLockKey))
                {
                    Monitor.Pulse(m_lstLocks[objLockKey]);
                    Monitor.Exit(m_lstLocks[objLockKey]);
                    lock (m_lstLocks)
                    {
                        //如果可以尝试获得锁,则表示没有其他地方使用锁,则移除锁
                        if (Monitor.TryEnter(m_lstLocks[objLockKey], 0))
                        {
                            Monitor.Exit(m_lstLocks[objLockKey]);
                            m_lstLocks.Remove(objLockKey);
                        }
                    }
                }
            }
            #endregion
    
            /// <summary>
            /// 功能描述:设置锁
            ////// 创建日期:2018-06-07 11:59:44
            ////// </summary>
            /// <param name="obj">obj</param>
            private void SetLockObj(object obj)
            {
                if (obj is string)
                {
                    if (string.IsNullOrEmpty(LockFormate) || LockFormate.IndexOf("{0}") < 0)
                    {
                        LockFormate = "{0}";
                    }
                    objLockKey = string.Format(LockFormate, obj).GetHashCode();
                }
                else
                {
                    objLockKey = obj.GetHashCode();
                }
            }
    
            /// <summary>
            /// 功能描述:在指定对象上获取排他锁。
            ////// 创建日期:2018-06-07 10:25:29
            ////// </summary>
            /// <param name="obj">在其上获取监视器锁的对象</param>
            public void Enter(object obj)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                Monitor.Enter(m_lstLocks[objLockKey]);
            }
    
            /// <summary>
            /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 10:27:21
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为true</param>
            public void Enter(object obj, ref bool lockTaken)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                Monitor.Enter(m_lstLocks[objLockKey], ref lockTaken);
            }
    
            /// <summary>
            /// 功能描述:释放指定对象上的排他锁
            ////// 创建日期:2018-06-07 10:36:51
            ////// </summary>
            /// <param name="obj">在其上释放锁的对象</param>
            public void Exit(object obj)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return;
                    }
                }
                Monitor.Exit(m_lstLocks[objLockKey]);
            }
    
            /// <summary>
            /// 功能描述:通知等待队列中的线程锁定对象状态的更改。
            ////// 创建日期:2018-06-07 10:37:15
            ////// </summary>
            /// <param name="obj">线程正在等待的对象</param>
            public void Pulse(object obj)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return;
                    }
                }
                Monitor.Pulse(m_lstLocks[objLockKey]);
            }
    
            /// <summary>
            /// 功能描述:通知所有的等待线程对象状态的更改。
            ////// 创建日期:2018-06-07 10:37:40
            ////// </summary>
            /// <param name="obj">发送脉冲的对象</param>
            public void PulseAll(object obj)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return;
                    }
                }
                Monitor.PulseAll(m_lstLocks[objLockKey]);
            }
    
            /// <summary>
            /// 功能描述:尝试获取指定对象的排他锁
            ////// 创建日期:2018-06-07 10:37:55
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象。</param>
            /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
            public bool TryEnter(object obj)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                bool bln = Monitor.TryEnter(m_lstLocks[objLockKey]);
                if (!bln)
                {
                    lock (m_lstLocks)
                    {
                        m_lstLocks.Remove(objLockKey);
                    }
                }
                return bln;
            }
    
            /// <summary>
            /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:38:11
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
            /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
            public bool TryEnter(object obj, int millisecondsTimeout)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                bool bln = Monitor.TryEnter(m_lstLocks[objLockKey], millisecondsTimeout);
                if (!bln)
                {
                    lock (m_lstLocks)
                    {
                        m_lstLocks.Remove(objLockKey);
                    }
                }
                return bln;
            }
    
            /// <summary>
            /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:38:34
            ////// </summary>
            /// <param name="obj">obj</param>
            /// <param name="lockTaken">lockTaken</param>
            public void TryEnter(object obj, ref bool lockTaken)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                Monitor.TryEnter(m_lstLocks[objLockKey], ref  lockTaken);
                if (!lockTaken)
                {
                    if (!lockTaken)
                    {
                        lock (m_lstLocks)
                        {
                            m_lstLocks.Remove(objLockKey);
                        }
                    }
                }
            }
    
            /// <summary>
            /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:39:28
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="timeout">System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
            /// <returns>如果当前线程在不阻止的情况下获取该锁,则为 true;否则为 false</returns>
            public bool TryEnter(object obj, TimeSpan timeout)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                bool lockTaken = Monitor.TryEnter(m_lstLocks[objLockKey], timeout);
                if (!lockTaken)
                {
                    lock (m_lstLocks)
                    {
                        m_lstLocks.Remove(objLockKey);
                    }
                }
                return lockTaken;
            }
    
            /// <summary>
            /// 功能描述:在指定的毫秒数中,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁
            ////// 创建日期:2018-06-07 10:40:54
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
            public void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                Monitor.TryEnter(m_lstLocks[objLockKey], millisecondsTimeout, ref  lockTaken);
                if (!lockTaken)
                {
                    lock (m_lstLocks)
                    {
                        m_lstLocks.Remove(objLockKey);
                    }
                }
            }
    
            /// <summary>
            /// 功能描述:在指定的一段时间内,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 11:12:21
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="timeout">用于等待锁的时间。值为 -1 毫秒表示指定无限期等待</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
            public void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
                    }
                }
                Monitor.TryEnter(m_lstLocks[objLockKey], timeout, ref  lockTaken);
                if (!lockTaken)
                {
                    lock (m_lstLocks)
                    {
                        m_lstLocks.Remove(objLockKey);
                    }
                }
            }
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。
            ////// 创建日期:2018-06-07 11:12:45
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <returns> 如果调用由于调用方重新获取了指定对象的锁而返回,则为 true。如果未重新获取该锁,则此方法不会返回。</returns>
            public bool Wait(object obj)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return false;
                    }
                }
                return Monitor.Wait(m_lstLocks[objLockKey]);
            }
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
            ////// 创建日期:2018-06-07 11:13:13
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            public bool Wait(object obj, int millisecondsTimeout)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return false;
                    }
                }
                return Monitor.Wait(m_lstLocks[objLockKey], millisecondsTimeout);
            }
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
            ////// 创建日期:2018-06-07 11:13:35
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量。</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            public bool Wait(object obj, TimeSpan timeout)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return false;
                    }
                }
                return Monitor.Wait(m_lstLocks[objLockKey], timeout);
            }
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。此方法还指定是否在等待之前退出上下文的同步域(如果处于同步上下文中的话)然后重新获取该同步域。
            ////// 创建日期:2018-06-07 11:14:02
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
            /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            public bool Wait(object obj, int millisecondsTimeout, bool exitContext)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return false;
                    }
                }
                return Monitor.Wait(m_lstLocks[objLockKey], millisecondsTimeout, exitContext);
            }
    
            /// <summary>
            /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。可以在等待之前退出同步上下文的同步域,随后重新获取该域。
            ////// 创建日期:2018-06-07 11:14:34
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量</param>
            /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
            /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
            public bool Wait(object obj, TimeSpan timeout, bool exitContext)
            {
                SetLockObj(obj);
                lock (m_lstLocks)
                {
                    if (!m_lstLocks.ContainsKey(objLockKey))
                    {
                        return false;
                    }
                }
                return Monitor.Wait(m_lstLocks[objLockKey], timeout, exitContext);
            }
    
            /// <summary>
            /// 功能描述:在指定对象上获取排他锁
            ////// 创建日期:2018-06-07 10:09:25
            ////// </summary>
            /// <param name="obj">在其上获取监视器锁的对象</param>     
            /// <returns>ILockExt对象</returns>
            public ILockExt EnterLock(object obj)
            {
                Enter(obj);
                return this;
            }
            /// <summary>
            /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 10:10:02
            ////// </summary>
            /// <param name="obj">要在其上等待的对象</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。Note如果没有发生异常,则此方法的输出始终为true</param>
            /// <returns>ILockExt对象</returns>
            public ILockExt EnterLock(object obj, ref bool lockTaken)
            {
                Enter(obj, ref lockTaken);
                return this;
            }
            /// <summary>
            /// 功能描述:尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
            ////// 创建日期:2018-06-07 10:17:29
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
            /// <returns>返回值</returns>
            public ILockExt TryEnterLock(object obj, ref bool lockTaken)
            {
                TryEnter(obj, ref lockTaken);
                return this;
            }
            /// <summary>
            /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:14:36
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
            /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
            /// <returns>ILockExt对象</returns>
            public ILockExt TryEnterLock(object obj, int millisecondsTimeout, ref bool lockTaken)
            {
                TryEnter(obj, millisecondsTimeout, ref lockTaken);
                return this;
            }
            /// <summary>
            /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
            ////// 创建日期:2018-06-07 10:15:50
            ////// </summary>
            /// <param name="obj">在其上获取锁的对象</param>
            /// <param name="timeout"> System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
            /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
            /// <returns>ILockExt对象</returns>
            public ILockExt TryEnterLock(object obj, TimeSpan timeout, ref bool lockTaken)
            {
                TryEnter(obj, timeout, ref lockTaken);
                return this;
            }
        }
    }
    View Code

    定义业务锁

    //// 文件名称:LockExtList.cs
    //// 创建日期:2018-06-07 11:46:47
    // 功能描述:锁列表
    //
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Km.Utils.Helpers
    {
        /* 说明
         * 注:
         * 编写锁步骤说明:
         * 1、编写对应类继承LockExt
         * 2、编写属性如下
         *   public static ILockExt Instance
            {
                get
                {
                    LockOfTable l = new LockOfTable();
                    l.LockFormate = "BillTableLock({0})";
                    return l;               
                }
            }
         * 
         * 使用锁说明:
         * 1、快捷使用如下
         *      //排队获得锁
         *      using (LockOfTable.Instance.EnterLock("台位号"))
         *      {
         *          //你的操作
         *      }
         *      //尝试获得锁
         *      bool blnLockTaken = false;
         *      using (LockOfTable.Instance.TryEnterLock("台位号", ref blnLockTaken))
         *      {
         *          if (!blnLockTaken)
         *          {
         *              //台位已被锁定
         *              return;
         *          }
         *          //你的操作
         *      }
         * 
         * 2、普通使用如下(更多的控制,但是要手动调用Exit进行释放锁)
         *      LockOfTable tableLock = LockOfTable.Instance;
         *      tableLock.Enter("台位号");
         *      tableLock.Pulse("台位号");
         *      tableLock.Wait("台位号");
         *      tableLock.Exit("台位号");
         *      ...
         */
    
        #region 台位锁
        /// <summary>
        /// 功能描述:台位锁
        ////// 创建日期:2018-06-07 11:30:45
        ////// </summary>
        public class LockOfTable : LockExt
        {
            public static ILockExt Instance
            {
                get
                {
                    LockOfTable l = new LockOfTable();
                    l.LockFormate = "BillTableLock({0})";
                    return l;               
                }
            }
        }
        #endregion
    
        #region 出品单锁
        /// <summary>
        /// 功能描述:出品单锁
        ////// 创建日期:2018-06-07 11:35:56
        ////// </summary>
        public class LockOfBill0 : LockExt
        {
            public static ILockExt Instance
            {
                get
                {
                    LockOfTable l = new LockOfTable();
                    l.LockFormate = "Bill0Lock({0})";
                    return l;
                }
            }
        }
        #endregion
    }
    View Code

    使用

     using (LockOfTable.Instance.EnterLock("123456"))
                {
                    Console.WriteLine("enter:" + i);
                    Console.WriteLine(i);
                    Thread.Sleep(1000);
                }
    View Code
  • 相关阅读:
    骥遇伯乐,关键的一点是人与事的匹配
    好习惯改变一生
    工作中如何面对挫折 [转帖]
    教育心理学领域有一句经典名言
    接触之,熟悉之,打破之
    成年人的35个好习惯(收藏)
    如何树立威信
    人际关系的55个绝招
    人际交往常见几种心理障碍 -实用
    人生成长必须知道的20则故事!
  • 原文地址:https://www.cnblogs.com/bfyx/p/9151081.html
Copyright © 2020-2023  润新知