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);
}
}
定义基类
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#自定义业务锁的更多相关文章
- AQS 自定义同步锁,挺难的!
AQS是AbstractQueuedSynchronizer的简称. AbstractQueuedSynchronizer 同步状态 AbstractQueuedSynchronizer 内部有一个s ...
- Python 36 GIL全局解释器锁 、vs自定义互斥锁
一:GIL全局解释器锁介绍 在CPython中,全局解释器锁(或GIL)是一个互斥锁, 它阻止多个本机线程同时执行Python字节码.译文:之所以需要这个锁, 主要是因为CPython的内存管理不是线 ...
- redis 业务锁 not exist 模式
背景: 业务核心模块只能提交一次,原实现方案 前端加提交限制.后端加数据库业务逻辑判定,结果失效,api站点部署多台负载,切方法需要强求第三方接口 响应时间较慢 ,故放弃lock. 解决方案:redi ...
- 基于官方镜像MySQL做自定义业务扩充镜像
转自:https://www.cnblogs.com/jsonhc/p/7809571.html 首先从https://hub.docker.com/_/mysql/拉取官方镜像,如果速度缓慢,建议添 ...
- 基于elasticsearch的自定义业务告警的设计思路
A系统与B系统之间有很多接口交互,但是有一段时间接口经常报错,作为开发如果不能第一时间知道问题且及时解决的话就会收到业务投诉,当月绩效凉凉. 如果你也有这种场景,那么你就需要一个及时告警的功能. 实现 ...
- JSP自定义业务标签
自定义标签: package cn.hv.tag; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; ...
- PHP (Yii2) 自定义业务异常类(可支持返回任意自己想要的类型数据)
public function beforeAction($action) { return parent::beforeAction($action); } public function runA ...
- 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 ...
- 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 ...
随机推荐
- C语言笔试题精选3---死锁发生必要条件是?
问:以下哪些是死锁发生必要条件? A.相互排斥条件 B.请求和保持 C.不可剥夺 D.循环等待 具体解答: 1.相互排斥使用(资源独占) 一个资源每次仅仅能给一个进程使用 2.不可强占(不可剥夺) ...
- 单点登录原理与简单实现--good
一.单系统登录机制 1.http无状态协议 web应用采用browser/server架构,http作为通信协议.http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的请求产生关 ...
- 利用WPF建立自己的3d gis软件(非axhost方式)(四)在地图上添加FrameworkElement
原文:利用WPF建立自己的3d gis软件(非axhost方式)(四)在地图上添加FrameworkElement 先下载SDK:https://pan.baidu.com/s/1M9kBS6ouUw ...
- express笔记
1.req.query: 获取get请求的查询字符串对象 2.req.body: 获取post请求的查询字符串对象,要使用该方法需要先使用body-parser中间件,app.use(bodyPars ...
- Hadoop和RDBMS的混合系统介绍
现在大数据概念被时常提起,社会各界对其关注度越来越高.往往越是火热的东西,人们越容易忽略它的本质.在 slides 中,我首先按照自己的理解,简单的理顺数据处理领域的发展历程.之后,落脚点是两个比较有 ...
- 如何控制WAP网站上输入框的默认键盘类型
百度上对这样的资料介绍很多,基本上都和这个页面是一个意思 http://www.w3school.com.cn/html5/att_input_type.asp : 语法 <input type ...
- Jquery对象和dom对象获取html的方法
1)DOM对象 var domObj = document.getElementById("id"); //DOM对象 domObj.innerHTML;// domObj.out ...
- Blend_Effect
原文:Blend_Effect 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010265681/article/details/76651796 ...
- 在运行Hfile的MR如果任务client结束OOM
在运行MR将HDFS转换成HFile什么时候.例如,会发生以下的异常: 14/07/09 18:02:59 INFO mapred.JobClient: map 83% reduce 0% 14/0 ...
- Raw-OS备用事件源代码分析
作为分析的内核版本2014-04-15,基于1.05正式版,blogs我们会跟上的内核开发进度的最新版本,如果出现源代码的目光"???"的话.没有深究的部分是理解. Raw-OS官 ...