我们有这样的使用场景,某个订单在修改信息的时候,其他人不能修改相关的信息,比如不能做支付,不能退单等等,那么我们可以根据单号进行加锁,多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);
}
}

定义基类

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 != && m_lstLocks.ContainsKey(objLockKey))
{
Monitor.Pulse(m_lstLocks[objLockKey]);
Monitor.Exit(m_lstLocks[objLockKey]);
lock (m_lstLocks)
{
//如果可以尝试获得锁,则表示没有其他地方使用锁,则移除锁
if (Monitor.TryEnter(m_lstLocks[objLockKey], ))
{
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}") < )
{
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;
}
}
}

定义业务锁

//// 文件名称: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
}

使用

 using (LockOfTable.Instance.EnterLock(""))
{
Console.WriteLine("enter:" + i);
Console.WriteLine(i);
Thread.Sleep();
}

c#自定义业务锁的更多相关文章

  1. AQS 自定义同步锁,挺难的!

    AQS是AbstractQueuedSynchronizer的简称. AbstractQueuedSynchronizer 同步状态 AbstractQueuedSynchronizer 内部有一个s ...

  2. Python 36 GIL全局解释器锁 、vs自定义互斥锁

    一:GIL全局解释器锁介绍 在CPython中,全局解释器锁(或GIL)是一个互斥锁, 它阻止多个本机线程同时执行Python字节码.译文:之所以需要这个锁, 主要是因为CPython的内存管理不是线 ...

  3. redis 业务锁 not exist 模式

    背景: 业务核心模块只能提交一次,原实现方案 前端加提交限制.后端加数据库业务逻辑判定,结果失效,api站点部署多台负载,切方法需要强求第三方接口 响应时间较慢 ,故放弃lock. 解决方案:redi ...

  4. 基于官方镜像MySQL做自定义业务扩充镜像

    转自:https://www.cnblogs.com/jsonhc/p/7809571.html 首先从https://hub.docker.com/_/mysql/拉取官方镜像,如果速度缓慢,建议添 ...

  5. 基于elasticsearch的自定义业务告警的设计思路

    A系统与B系统之间有很多接口交互,但是有一段时间接口经常报错,作为开发如果不能第一时间知道问题且及时解决的话就会收到业务投诉,当月绩效凉凉. 如果你也有这种场景,那么你就需要一个及时告警的功能. 实现 ...

  6. JSP自定义业务标签

    自定义标签: package cn.hv.tag; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; ...

  7. PHP (Yii2) 自定义业务异常类(可支持返回任意自己想要的类型数据)

    public function beforeAction($action) { return parent::beforeAction($action); } public function runA ...

  8. Implement Custom Business Classes and Reference Properties实现自定义业务类和引用属性(EF)

    In this lesson, you will learn how to implement business classes from scratch. For this purpose, the ...

  9. Implement Custom Business Classes and Reference Properties 实现自定义业务类和引用属性(XPO)

    In this lesson, you will learn how to implement business classes from scratch. For this purpose, the ...

随机推荐

  1. Linux环境下搭建VPS服务

    说明 由于大部分VPN被封,FQ过程中无意间接触到了VPS(Virtual Private Server 虚拟专用服务器,可用于FQ),所以简单记录下VPS服务搭建流程. 此教程基于centos7,本 ...

  2. 微信支付-公众号支付H5调用支付详解

    微信公众号支付 最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验. 一. ...

  3. hadoop 3.x 关闭安全模式

    hdfs启动后发现进入了安全模式,最开始使用hdfs dfsadmin -safemode leave来进行关闭发现无法关闭,只好使用hdfs dfsadmin -safemode forceExit ...

  4. hexo的url路径修改以及发布与修改时间

    hexo默认url是年/月/日,这样其实不利于SEO.hexo生成新文章命令,hexo new [layout] <title>,这个title最好是英文的,因为我们要把这个title放在 ...

  5. Qt5信号与槽C++11风格连接简介

    最近在论坛上看到了这个方面的问题,详见这里. 随后浅浅地学习了一下子,看到了Qt官方论坛上给出的说明,觉得C++11的functional连接方法还是比Qt4既有的宏连接方法有很大不同. 官方论坛的文 ...

  6. wpf控件开发基础(3) -属性系统(2)

    原文:wpf控件开发基础(3) -属性系统(2) 上篇说明了属性存在的一系列问题. 属性默认值,可以保证属性的有效性. 属性验证有效性,可以对输入的属性进行校验 属性强制回调, 即不管属性有无发生变化 ...

  7. POJ 1988 Cube Stacking (种类并查集)

    题目地址:POJ 1988 这道题的查找合并的方法都能想的到,就是一点没想到,我一直天真的以为查询的时候,输入后能立即输出,这种话在合并的时候就要所有的结点值都要算出来,可是经过路径压缩之后,没办法所 ...

  8. Android于popWindow写弹出菜单

    1.什么是popWindow? popWindow这是对话的方式!文字解说android的方式来使用对话框,这就是所谓的popWindow. 2.popWindow特征 Android的对话框有两种: ...

  9. golang中jwt使用

    golang 中jwt使用方式总结. 1. golang示例代码 import ( "fmt" "time" "github.com/dgrijalv ...

  10. 亲串 (hdu 2203 KMP)

    亲串 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...