我们有这样的使用场景,某个订单在修改信息的时候,其他人不能修改相关的信息,比如不能做支付,不能退单等等,那么我们可以根据单号进行加锁,多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. android tips—开机引导启动wifi设置

    在开机引导(Setupwizard,Guide)中都有关于wifi设置项,我得做法例如以下: Intent intent = new Intent(); intent.setClassName(&qu ...

  2. 【26.67%】【codeforces 596C】Wilbur and Points

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  3. java.lang.ExceptionInInitializerError异常分析

    今天在项目开发时遇到一个问题,整个项目是使用Spring等框架搭建起来的在运行项目时不报任何的异常信息,就是找不到某个类信息,各方查找该类确实是存在的,最后通过断点跟踪时在异常栈内发现java.lan ...

  4. React Native中的DeviceEventEmitter.addListener与DeviceEventEmitter.emit

    官方文档没有对这两个方法做很好的解释,需要自己找资料研究.看了几篇文章,总结是和订阅发布模式差不多,用来事件监听发送的. React Native学习之DeviceEventEmitter传值   R ...

  5. 衡量镜头解像能力性能的指标-MTF曲线

    MTF(Modulation Transfer Function,模量传递函数),是目前分析镜头解像能力的方法,可以用来评判镜头还原物体对比度的能力.说到MTF,不得不先提一下衡量镜头性能的两在重要指 ...

  6. numpy 辨异(二) —— np.identity()/np.eye()

    import numpy as np; 两者在创建单位矩阵上,并无区别,两者的区别主要在接口上: np.identity(n, dtype=None):只能获取方阵,也即标准意义的单位阵: np.ey ...

  7. quick-cocos2d-x游戏开发【8】——动画与动作

    动画与动作,在quick中都有对其封装,所以我们还是来看一下吧. 总的来说,对于帧动画,quick封装的方法我们能够常常使用,这是很方便的,以下直接上代码来直观感受下, 比方,14张帧图片,採用coc ...

  8. OpenGL(六) gluLookAt和gluPerspective函数解析

    在调用gluLookAt和gluPerspective函数之前一般要先调用一下glLoadIdentity函数,先说一下这个函数是做什么的. glLoadIdentity glLoadIdentity ...

  9. Android Ant 和 Gradle 包装工艺和效率控制

    一个.Ant 包:(下载ant.配置环境变量不说) 1.进入命令行模式,并切换到项目文件夹,运行例如以下命令为ADT创建的项目加入ant build支持: android update project ...

  10. C# NetCore使用AngleSharp爬取周公解梦数据

    这一章详细讲解编码过程 那么接下来就是码代码了,GO 新建NetCore WebApi项目 空的就可以 NuGet安装 Install-Package AngleSharp 或者界面安装 using. ...