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

    题意:在n*m的矩阵中,有些格子有树,没有树的格子不能到达,找一条或多条回路,吃全然部的树,求有多少中方法. 这题是插头dp,刚刚学习,不是非常熟悉,研究了好几天才明确插头dp的方法,他们老是讲一些什 ...

  2. C# Span 入门

    原文:C# Span 入门 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.io 访问博客.本 ...

  3. HTML 基础知识(特殊字符的转义)

    1. body.head(meta) <body></body>标签的常见属性: bgcolor:整个页面的背景: text:设置文本颜色 link:设置连接颜色(),vlin ...

  4. c#开发移动APP-Xamarin入门剖析

    原文:c#开发移动APP-Xamarin入门剖析 剖析应用程序 Phoneword这个项目是.net标准库项目,它包含所有的共享代码和共享UI. Phoneword.Android这个项目包含Andr ...

  5. WPF 实现拖动工具箱效果

    原文:WPF 实现拖动工具箱效果 1.效果 点击左边的矩形拖动到右边canvas面板,右边面板添加矩形 2.布局 左边是个StockPanel,上面有个矩形,右边是个Canvas面板. 矩形是源,Ca ...

  6. matlab 各种文件的读取(及读写问题的解决)

    0. 文本文件 load('**.mat') load('**.mat', '-ascii') load('-mat', filename) load('-ascii', filename) 1. 音 ...

  7. [科普]MinGW vs MinGW-W64及其它(比较有意思,来自mingw吧)

    部分参照备忘录原文: bitbucket.org/FrankHB/yslib/src/50c3e6344a5a24b2382ce3398065f2197c2bd57e/doc/Workflow.Ann ...

  8. 优雅实现INotifyPropertyChanged接口——利用Lambda表达式

    原文:优雅实现INotifyPropertyChanged接口--利用Lambda表达式 参考文章 在14年的时候,曾经读过上面的参考文章,不过当时并没有怎么理解,慢慢地也就将这篇文章忘诸脑后了. 直 ...

  9. WCF配置文件详解

    今天来看看WCF的配置方法. 上图整理了服务配置过程中所用到的基本的元素,大致的步骤主要是首先要在调用服务的程序集中添加服务的一个引用,然后添加一个service并指定服务的名称.终结点,如果添加了b ...

  10. WPF HeaderedContentControl两个内容属性 Header和Content

    <Window x:Class="XamlTest.Window2"        xmlns="http://schemas.microsoft.com/winf ...