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

    2010中的StringBuilder对象用的比较爽快!于是稍作了一些修改(增加了几个函数和属性)然后移植到D2007中来使用了!效果不错,共享一下! unit DxStringBuilder; in ...

  2. Bean行为破坏之前,

    而在自定义初始化阶段的行为之一似.Spring此外,它提供了两种方法来定制Bean具体的行为破坏之前. 例如下列: 1.采用destroy-method属性. 2.达到DisposableBean介面 ...

  3. 使用JScript脚本批量修改VC工程设置

    作者:朱金灿 来源:http://blog.csdn.net/clever101 很多时候升级了第三方库,需要对很多工程修改设置.在VS中按住Ctrl键确实可以多选工程,但通过这样做也有麻烦的地方:一 ...

  4. vs2008C1902数据库管理程序不匹配

    打开一大早vs2008,有这么奇怪的错误, 删了dll正好.图. 版权声明:本文博主原创文章.博客,未经同意不得转载.

  5. MFC和Qt优缺点 (MFC几乎没有优点、全面下风)

    在网上看到的,拿来和大家一起讨论下. 我曾经使用过来开发过软件,我想和大家分享我使用他们时所体会的不同之处. 我并非一个职业作家,这篇文章可能看起来不如专业的杂志和网站上的那么条理清晰.但是,我在这里 ...

  6. 各种工具的使用 tricks

    1. 搜狗搜索引擎 因为搜狗与腾讯的合作关系,搜狗搜索引擎提供了"微信"的搜索选项,可直接定位到相关文章,或者公众号. weixin.sougou.com 2. PyCharm P ...

  7. C# WPF 低仿网易云音乐(PC)Banner动画控件

    原文:C# WPF 低仿网易云音乐(PC)Banner动画控件 由于技术有限没能做到一模一样的动画,只是粗略地做了一下.动画有点生硬,还有就是没做出网易云音乐的立体感.代码非常简单粗暴,而且我也写有很 ...

  8. AvalonDock的基本用法

    原文:AvalonDock的基本用法         AvalonDock是优秀的开源项目,用于创建可停靠式布局,能够在WPF中方便开发出类似VS2010的软件界面.对于复杂的软件系统,大量控件的使用 ...

  9. 写在程序猿的困惑(特别Java程序猿)入行一年,感觉我不知道接下来该怎么办才能不断进步的,寻求翼

    入行了一年.感觉不知道接下来该怎么做才干继续进步了,求不吝赐教(V2EX) @kafka0102 :做技术能够学的东西太多了.仅仅是在不同的阶段做好不同的规划.要结合当前所做的事情去做更深入或广度的学 ...

  10. matlab 矢量化编程(三) —— 软阈值函数

    dj,k^=⎧⎩⎨⎪⎪dj,k−λ,dj,k≥λ0,otherwisedj,k+λ,dj,k≤−λ function y = soft(x, T) y = (x - abs(T) > 0) .* ...