我们有这样的使用场景,某个订单在修改信息的时候,其他人不能修改相关的信息,比如不能做支付,不能退单等等,那么我们可以根据单号进行加锁,多Monitor做了如下扩展

定义接口

  1. //// 文件名称:ILockExt.cs
  2. //// 创建日期:2018-06-07 10:44:39
  3. // 功能描述:自定义锁接口
  4. //
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Runtime.ConstrainedExecution;
  9. using System.Text;
  10.  
  11. namespace Km.Utils.Helpers
  12. {
  13. /// <summary>
  14. /// 功能描述:自定义锁接口
  15. ////// 创建日期:2018-06-07 10:41:47
  16. ////// </summary>
  17. public interface ILockExt : IDisposable
  18. {
  19. /// <summary>
  20. /// 功能描述:在指定对象上获取排他锁。
  21. ////// 创建日期:2018-06-07 10:25:29
  22. ////// </summary>
  23. /// <param name="obj">在其上获取监视器锁的对象</param>
  24. void Enter(object obj);
  25.  
  26. /// <summary>
  27. /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  28. ////// 创建日期:2018-06-07 10:27:21
  29. ////// </summary>
  30. /// <param name="obj">要在其上等待的对象</param>
  31. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为true</param>
  32. void Enter(object obj, ref bool lockTaken);
  33.  
  34. /// <summary>
  35. /// 功能描述:释放指定对象上的排他锁
  36. ////// 创建日期:2018-06-07 10:36:51
  37. ////// </summary>
  38. /// <param name="obj">在其上释放锁的对象</param>
  39. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  40. void Exit(object obj);
  41.  
  42. /// <summary>
  43. /// 功能描述:通知等待队列中的线程锁定对象状态的更改。
  44. ////// 创建日期:2018-06-07 10:37:15
  45. ////// </summary>
  46. /// <param name="obj">线程正在等待的对象</param>
  47. void Pulse(object obj);
  48.  
  49. /// <summary>
  50. /// 功能描述:通知所有的等待线程对象状态的更改。
  51. ////// 创建日期:2018-06-07 10:37:40
  52. ////// </summary>
  53. /// <param name="obj">发送脉冲的对象</param>
  54. void PulseAll(object obj);
  55.  
  56. /// <summary>
  57. /// 功能描述:尝试获取指定对象的排他锁
  58. ////// 创建日期:2018-06-07 10:37:55
  59. ////// </summary>
  60. /// <param name="obj">在其上获取锁的对象。</param>
  61. /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
  62. bool TryEnter(object obj);
  63.  
  64. /// <summary>
  65. /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
  66. ////// 创建日期:2018-06-07 10:38:11
  67. ////// </summary>
  68. /// <param name="obj">在其上获取锁的对象</param>
  69. /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
  70. /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
  71. bool TryEnter(object obj, int millisecondsTimeout);
  72.  
  73. /// <summary>
  74. /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
  75. ////// 创建日期:2018-06-07 10:38:34
  76. ////// </summary>
  77. /// <param name="obj">obj</param>
  78. /// <param name="lockTaken">lockTaken</param>
  79. void TryEnter(object obj, ref bool lockTaken);
  80.  
  81. /// <summary>
  82. /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
  83. ////// 创建日期:2018-06-07 10:39:28
  84. ////// </summary>
  85. /// <param name="obj">在其上获取锁的对象</param>
  86. /// <param name="timeout">System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
  87. /// <returns>如果当前线程在不阻止的情况下获取该锁,则为 true;否则为 false</returns>
  88. bool TryEnter(object obj, TimeSpan timeout);
  89.  
  90. /// <summary>
  91. /// 功能描述:在指定的毫秒数中,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁
  92. ////// 创建日期:2018-06-07 10:40:54
  93. ////// </summary>
  94. /// <param name="obj">在其上获取锁的对象</param>
  95. /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
  96. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
  97. void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken);
  98.  
  99. /// <summary>
  100. /// 功能描述:在指定的一段时间内,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  101. ////// 创建日期:2018-06-07 11:12:21
  102. ////// </summary>
  103. /// <param name="obj">在其上获取锁的对象</param>
  104. /// <param name="timeout">用于等待锁的时间。值为 -1 毫秒表示指定无限期等待</param>
  105. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
  106. void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken);
  107.  
  108. /// <summary>
  109. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。
  110. ////// 创建日期:2018-06-07 11:12:45
  111. ////// </summary>
  112. /// <param name="obj">要在其上等待的对象</param>
  113. /// <returns> 如果调用由于调用方重新获取了指定对象的锁而返回,则为 true。如果未重新获取该锁,则此方法不会返回。</returns>
  114. bool Wait(object obj);
  115.  
  116. /// <summary>
  117. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
  118. ////// 创建日期:2018-06-07 11:13:13
  119. ////// </summary>
  120. /// <param name="obj">要在其上等待的对象</param>
  121. /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
  122. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  123. bool Wait(object obj, int millisecondsTimeout);
  124.  
  125. /// <summary>
  126. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
  127. ////// 创建日期:2018-06-07 11:13:35
  128. ////// </summary>
  129. /// <param name="obj">要在其上等待的对象</param>
  130. /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量。</param>
  131. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  132. bool Wait(object obj, TimeSpan timeout);
  133.  
  134. /// <summary>
  135. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。此方法还指定是否在等待之前退出上下文的同步域(如果处于同步上下文中的话)然后重新获取该同步域。
  136. ////// 创建日期:2018-06-07 11:14:02
  137. ////// </summary>
  138. /// <param name="obj">要在其上等待的对象</param>
  139. /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
  140. /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
  141. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  142. bool Wait(object obj, int millisecondsTimeout, bool exitContext);
  143.  
  144. /// <summary>
  145. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。可以在等待之前退出同步上下文的同步域,随后重新获取该域。
  146. ////// 创建日期:2018-06-07 11:14:34
  147. ////// </summary>
  148. /// <param name="obj">要在其上等待的对象</param>
  149. /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量</param>
  150. /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
  151. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  152. bool Wait(object obj, TimeSpan timeout, bool exitContext);
  153.  
  154. /// <summary>
  155. /// 功能描述:在指定对象上获取排他锁
  156. ////// 创建日期:2018-06-07 10:09:25
  157. ////// </summary>
  158. /// <param name="obj">在其上获取监视器锁的对象</param>
  159. /// <returns>ILockExt对象</returns>
  160. ILockExt EnterLock(object obj);
  161. /// <summary>
  162. /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  163. ////// 创建日期:2018-06-07 10:10:02
  164. ////// </summary>
  165. /// <param name="obj">要在其上等待的对象</param>
  166. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。Note如果没有发生异常,则此方法的输出始终为true</param>
  167. /// <returns>ILockExt对象</returns>
  168. ILockExt EnterLock(object obj, ref bool lockTaken);
  169. /// <summary>
  170. /// 功能描述:尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  171. ////// 创建日期:2018-06-07 10:17:29
  172. ////// </summary>
  173. /// <param name="obj">在其上获取锁的对象</param>
  174. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
  175. /// <returns>返回值</returns>
  176. ILockExt TryEnterLock(object obj, ref bool lockTaken);
  177. /// <summary>
  178. /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
  179. ////// 创建日期:2018-06-07 10:14:36
  180. ////// </summary>
  181. /// <param name="obj">在其上获取锁的对象</param>
  182. /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
  183. /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
  184. /// <returns>ILockExt对象</returns>
  185. ILockExt TryEnterLock(object obj, int millisecondsTimeout, ref bool lockTaken);
  186. /// <summary>
  187. /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
  188. ////// 创建日期:2018-06-07 10:15:50
  189. ////// </summary>
  190. /// <param name="obj">在其上获取锁的对象</param>
  191. /// <param name="timeout"> System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
  192. /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
  193. /// <returns>ILockExt对象</returns>
  194. ILockExt TryEnterLock(object obj, TimeSpan timeout, ref bool lockTaken);
  195. }
  196. }

定义基类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6.  
  7. namespace Km.Utils.Helpers
  8. {
  9. /// <summary>
  10. /// 功能描述:自定义锁
  11. ////// 创建日期:2018-06-07 10:49:26
  12. ////// </summary>
  13. public class LockExt : ILockExt
  14. {
  15. private static Dictionary<int, string> m_lstLocks = new Dictionary<int, string>();
  16. /// <summary>
  17. /// 获取一个新实例
  18. /// </summary>
  19. public static ILockExt Instance
  20. {
  21. get
  22. {
  23. return new LockExt();
  24. }
  25. }
  26. /// <summary>
  27. /// 字符串锁类型格式化 by beck.huang 2018-06-07 11:00:25
  28. /// </summary>
  29. public string LockFormate
  30. {
  31. get;
  32. set;
  33. }
  34. //锁对象
  35. private int objLockKey;
  36.  
  37. #region 构造函数
  38. /// <summary>
  39. /// 功能描述:构造函数
  40. ////// 创建日期:2018-06-07 10:49:46
  41. ////// </summary>
  42. public LockExt()
  43. {
  44.  
  45. }
  46. /// <summary>
  47. /// 功能描述:执行与释放或重置非托管资源相关的应用程序定义的任务。
  48. ////// 创建日期:2018-06-07 10:49:18
  49. ////// </summary>
  50. public void Dispose()
  51. {
  52. if (objLockKey != && m_lstLocks.ContainsKey(objLockKey))
  53. {
  54. Monitor.Pulse(m_lstLocks[objLockKey]);
  55. Monitor.Exit(m_lstLocks[objLockKey]);
  56. lock (m_lstLocks)
  57. {
  58. //如果可以尝试获得锁,则表示没有其他地方使用锁,则移除锁
  59. if (Monitor.TryEnter(m_lstLocks[objLockKey], ))
  60. {
  61. Monitor.Exit(m_lstLocks[objLockKey]);
  62. m_lstLocks.Remove(objLockKey);
  63. }
  64. }
  65. }
  66. }
  67. #endregion
  68.  
  69. /// <summary>
  70. /// 功能描述:设置锁
  71. ////// 创建日期:2018-06-07 11:59:44
  72. ////// </summary>
  73. /// <param name="obj">obj</param>
  74. private void SetLockObj(object obj)
  75. {
  76. if (obj is string)
  77. {
  78. if (string.IsNullOrEmpty(LockFormate) || LockFormate.IndexOf("{0}") < )
  79. {
  80. LockFormate = "{0}";
  81. }
  82. objLockKey = string.Format(LockFormate, obj).GetHashCode();
  83. }
  84. else
  85. {
  86. objLockKey = obj.GetHashCode();
  87. }
  88. }
  89.  
  90. /// <summary>
  91. /// 功能描述:在指定对象上获取排他锁。
  92. ////// 创建日期:2018-06-07 10:25:29
  93. ////// </summary>
  94. /// <param name="obj">在其上获取监视器锁的对象</param>
  95. public void Enter(object obj)
  96. {
  97. SetLockObj(obj);
  98. lock (m_lstLocks)
  99. {
  100. if (!m_lstLocks.ContainsKey(objLockKey))
  101. {
  102. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  103. }
  104. }
  105. Monitor.Enter(m_lstLocks[objLockKey]);
  106. }
  107.  
  108. /// <summary>
  109. /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  110. ////// 创建日期:2018-06-07 10:27:21
  111. ////// </summary>
  112. /// <param name="obj">要在其上等待的对象</param>
  113. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为true</param>
  114. public void Enter(object obj, ref bool lockTaken)
  115. {
  116. SetLockObj(obj);
  117. lock (m_lstLocks)
  118. {
  119. if (!m_lstLocks.ContainsKey(objLockKey))
  120. {
  121. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  122. }
  123. }
  124. Monitor.Enter(m_lstLocks[objLockKey], ref lockTaken);
  125. }
  126.  
  127. /// <summary>
  128. /// 功能描述:释放指定对象上的排他锁
  129. ////// 创建日期:2018-06-07 10:36:51
  130. ////// </summary>
  131. /// <param name="obj">在其上释放锁的对象</param>
  132. public void Exit(object obj)
  133. {
  134. SetLockObj(obj);
  135. lock (m_lstLocks)
  136. {
  137. if (!m_lstLocks.ContainsKey(objLockKey))
  138. {
  139. return;
  140. }
  141. }
  142. Monitor.Exit(m_lstLocks[objLockKey]);
  143. }
  144.  
  145. /// <summary>
  146. /// 功能描述:通知等待队列中的线程锁定对象状态的更改。
  147. ////// 创建日期:2018-06-07 10:37:15
  148. ////// </summary>
  149. /// <param name="obj">线程正在等待的对象</param>
  150. public void Pulse(object obj)
  151. {
  152. SetLockObj(obj);
  153. lock (m_lstLocks)
  154. {
  155. if (!m_lstLocks.ContainsKey(objLockKey))
  156. {
  157. return;
  158. }
  159. }
  160. Monitor.Pulse(m_lstLocks[objLockKey]);
  161. }
  162.  
  163. /// <summary>
  164. /// 功能描述:通知所有的等待线程对象状态的更改。
  165. ////// 创建日期:2018-06-07 10:37:40
  166. ////// </summary>
  167. /// <param name="obj">发送脉冲的对象</param>
  168. public void PulseAll(object obj)
  169. {
  170. SetLockObj(obj);
  171. lock (m_lstLocks)
  172. {
  173. if (!m_lstLocks.ContainsKey(objLockKey))
  174. {
  175. return;
  176. }
  177. }
  178. Monitor.PulseAll(m_lstLocks[objLockKey]);
  179. }
  180.  
  181. /// <summary>
  182. /// 功能描述:尝试获取指定对象的排他锁
  183. ////// 创建日期:2018-06-07 10:37:55
  184. ////// </summary>
  185. /// <param name="obj">在其上获取锁的对象。</param>
  186. /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
  187. public bool TryEnter(object obj)
  188. {
  189. SetLockObj(obj);
  190. lock (m_lstLocks)
  191. {
  192. if (!m_lstLocks.ContainsKey(objLockKey))
  193. {
  194. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  195. }
  196. }
  197. bool bln = Monitor.TryEnter(m_lstLocks[objLockKey]);
  198. if (!bln)
  199. {
  200. lock (m_lstLocks)
  201. {
  202. m_lstLocks.Remove(objLockKey);
  203. }
  204. }
  205. return bln;
  206. }
  207.  
  208. /// <summary>
  209. /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
  210. ////// 创建日期:2018-06-07 10:38:11
  211. ////// </summary>
  212. /// <param name="obj">在其上获取锁的对象</param>
  213. /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
  214. /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns>
  215. public bool TryEnter(object obj, int millisecondsTimeout)
  216. {
  217. SetLockObj(obj);
  218. lock (m_lstLocks)
  219. {
  220. if (!m_lstLocks.ContainsKey(objLockKey))
  221. {
  222. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  223. }
  224. }
  225. bool bln = Monitor.TryEnter(m_lstLocks[objLockKey], millisecondsTimeout);
  226. if (!bln)
  227. {
  228. lock (m_lstLocks)
  229. {
  230. m_lstLocks.Remove(objLockKey);
  231. }
  232. }
  233. return bln;
  234. }
  235.  
  236. /// <summary>
  237. /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
  238. ////// 创建日期:2018-06-07 10:38:34
  239. ////// </summary>
  240. /// <param name="obj">obj</param>
  241. /// <param name="lockTaken">lockTaken</param>
  242. public void TryEnter(object obj, ref bool lockTaken)
  243. {
  244. SetLockObj(obj);
  245. lock (m_lstLocks)
  246. {
  247. if (!m_lstLocks.ContainsKey(objLockKey))
  248. {
  249. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  250. }
  251. }
  252. Monitor.TryEnter(m_lstLocks[objLockKey], ref lockTaken);
  253. if (!lockTaken)
  254. {
  255. if (!lockTaken)
  256. {
  257. lock (m_lstLocks)
  258. {
  259. m_lstLocks.Remove(objLockKey);
  260. }
  261. }
  262. }
  263. }
  264.  
  265. /// <summary>
  266. /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
  267. ////// 创建日期:2018-06-07 10:39:28
  268. ////// </summary>
  269. /// <param name="obj">在其上获取锁的对象</param>
  270. /// <param name="timeout">System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
  271. /// <returns>如果当前线程在不阻止的情况下获取该锁,则为 true;否则为 false</returns>
  272. public bool TryEnter(object obj, TimeSpan timeout)
  273. {
  274. SetLockObj(obj);
  275. lock (m_lstLocks)
  276. {
  277. if (!m_lstLocks.ContainsKey(objLockKey))
  278. {
  279. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  280. }
  281. }
  282. bool lockTaken = Monitor.TryEnter(m_lstLocks[objLockKey], timeout);
  283. if (!lockTaken)
  284. {
  285. lock (m_lstLocks)
  286. {
  287. m_lstLocks.Remove(objLockKey);
  288. }
  289. }
  290. return lockTaken;
  291. }
  292.  
  293. /// <summary>
  294. /// 功能描述:在指定的毫秒数中,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁
  295. ////// 创建日期:2018-06-07 10:40:54
  296. ////// </summary>
  297. /// <param name="obj">在其上获取锁的对象</param>
  298. /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
  299. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
  300. public void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken)
  301. {
  302. SetLockObj(obj);
  303. lock (m_lstLocks)
  304. {
  305. if (!m_lstLocks.ContainsKey(objLockKey))
  306. {
  307. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  308. }
  309. }
  310. Monitor.TryEnter(m_lstLocks[objLockKey], millisecondsTimeout, ref lockTaken);
  311. if (!lockTaken)
  312. {
  313. lock (m_lstLocks)
  314. {
  315. m_lstLocks.Remove(objLockKey);
  316. }
  317. }
  318. }
  319.  
  320. /// <summary>
  321. /// 功能描述:在指定的一段时间内,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  322. ////// 创建日期:2018-06-07 11:12:21
  323. ////// </summary>
  324. /// <param name="obj">在其上获取锁的对象</param>
  325. /// <param name="timeout">用于等待锁的时间。值为 -1 毫秒表示指定无限期等待</param>
  326. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
  327. public void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken)
  328. {
  329. SetLockObj(obj);
  330. lock (m_lstLocks)
  331. {
  332. if (!m_lstLocks.ContainsKey(objLockKey))
  333. {
  334. m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString());
  335. }
  336. }
  337. Monitor.TryEnter(m_lstLocks[objLockKey], timeout, ref lockTaken);
  338. if (!lockTaken)
  339. {
  340. lock (m_lstLocks)
  341. {
  342. m_lstLocks.Remove(objLockKey);
  343. }
  344. }
  345. }
  346.  
  347. /// <summary>
  348. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。
  349. ////// 创建日期:2018-06-07 11:12:45
  350. ////// </summary>
  351. /// <param name="obj">要在其上等待的对象</param>
  352. /// <returns> 如果调用由于调用方重新获取了指定对象的锁而返回,则为 true。如果未重新获取该锁,则此方法不会返回。</returns>
  353. public bool Wait(object obj)
  354. {
  355. SetLockObj(obj);
  356. lock (m_lstLocks)
  357. {
  358. if (!m_lstLocks.ContainsKey(objLockKey))
  359. {
  360. return false;
  361. }
  362. }
  363. return Monitor.Wait(m_lstLocks[objLockKey]);
  364. }
  365.  
  366. /// <summary>
  367. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
  368. ////// 创建日期:2018-06-07 11:13:13
  369. ////// </summary>
  370. /// <param name="obj">要在其上等待的对象</param>
  371. /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
  372. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  373. public bool Wait(object obj, int millisecondsTimeout)
  374. {
  375. SetLockObj(obj);
  376. lock (m_lstLocks)
  377. {
  378. if (!m_lstLocks.ContainsKey(objLockKey))
  379. {
  380. return false;
  381. }
  382. }
  383. return Monitor.Wait(m_lstLocks[objLockKey], millisecondsTimeout);
  384. }
  385.  
  386. /// <summary>
  387. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。
  388. ////// 创建日期:2018-06-07 11:13:35
  389. ////// </summary>
  390. /// <param name="obj">要在其上等待的对象</param>
  391. /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量。</param>
  392. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  393. public bool Wait(object obj, TimeSpan timeout)
  394. {
  395. SetLockObj(obj);
  396. lock (m_lstLocks)
  397. {
  398. if (!m_lstLocks.ContainsKey(objLockKey))
  399. {
  400. return false;
  401. }
  402. }
  403. return Monitor.Wait(m_lstLocks[objLockKey], timeout);
  404. }
  405.  
  406. /// <summary>
  407. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。此方法还指定是否在等待之前退出上下文的同步域(如果处于同步上下文中的话)然后重新获取该同步域。
  408. ////// 创建日期:2018-06-07 11:14:02
  409. ////// </summary>
  410. /// <param name="obj">要在其上等待的对象</param>
  411. /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param>
  412. /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
  413. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  414. public bool Wait(object obj, int millisecondsTimeout, bool exitContext)
  415. {
  416. SetLockObj(obj);
  417. lock (m_lstLocks)
  418. {
  419. if (!m_lstLocks.ContainsKey(objLockKey))
  420. {
  421. return false;
  422. }
  423. }
  424. return Monitor.Wait(m_lstLocks[objLockKey], millisecondsTimeout, exitContext);
  425. }
  426.  
  427. /// <summary>
  428. /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。可以在等待之前退出同步上下文的同步域,随后重新获取该域。
  429. ////// 创建日期:2018-06-07 11:14:34
  430. ////// </summary>
  431. /// <param name="obj">要在其上等待的对象</param>
  432. /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量</param>
  433. /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param>
  434. /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns>
  435. public bool Wait(object obj, TimeSpan timeout, bool exitContext)
  436. {
  437. SetLockObj(obj);
  438. lock (m_lstLocks)
  439. {
  440. if (!m_lstLocks.ContainsKey(objLockKey))
  441. {
  442. return false;
  443. }
  444. }
  445. return Monitor.Wait(m_lstLocks[objLockKey], timeout, exitContext);
  446. }
  447.  
  448. /// <summary>
  449. /// 功能描述:在指定对象上获取排他锁
  450. ////// 创建日期:2018-06-07 10:09:25
  451. ////// </summary>
  452. /// <param name="obj">在其上获取监视器锁的对象</param>
  453. /// <returns>ILockExt对象</returns>
  454. public ILockExt EnterLock(object obj)
  455. {
  456. Enter(obj);
  457. return this;
  458. }
  459. /// <summary>
  460. /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  461. ////// 创建日期:2018-06-07 10:10:02
  462. ////// </summary>
  463. /// <param name="obj">要在其上等待的对象</param>
  464. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。Note如果没有发生异常,则此方法的输出始终为true</param>
  465. /// <returns>ILockExt对象</returns>
  466. public ILockExt EnterLock(object obj, ref bool lockTaken)
  467. {
  468. Enter(obj, ref lockTaken);
  469. return this;
  470. }
  471. /// <summary>
  472. /// 功能描述:尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。
  473. ////// 创建日期:2018-06-07 10:17:29
  474. ////// </summary>
  475. /// <param name="obj">在其上获取锁的对象</param>
  476. /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param>
  477. /// <returns>返回值</returns>
  478. public ILockExt TryEnterLock(object obj, ref bool lockTaken)
  479. {
  480. TryEnter(obj, ref lockTaken);
  481. return this;
  482. }
  483. /// <summary>
  484. /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。
  485. ////// 创建日期:2018-06-07 10:14:36
  486. ////// </summary>
  487. /// <param name="obj">在其上获取锁的对象</param>
  488. /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param>
  489. /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
  490. /// <returns>ILockExt对象</returns>
  491. public ILockExt TryEnterLock(object obj, int millisecondsTimeout, ref bool lockTaken)
  492. {
  493. TryEnter(obj, millisecondsTimeout, ref lockTaken);
  494. return this;
  495. }
  496. /// <summary>
  497. /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。
  498. ////// 创建日期:2018-06-07 10:15:50
  499. ////// </summary>
  500. /// <param name="obj">在其上获取锁的对象</param>
  501. /// <param name="timeout"> System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param>
  502. /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param>
  503. /// <returns>ILockExt对象</returns>
  504. public ILockExt TryEnterLock(object obj, TimeSpan timeout, ref bool lockTaken)
  505. {
  506. TryEnter(obj, timeout, ref lockTaken);
  507. return this;
  508. }
  509. }
  510. }

定义业务锁

  1. //// 文件名称:LockExtList.cs
  2. //// 创建日期:2018-06-07 11:46:47
  3. // 功能描述:锁列表
  4. //
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9.  
  10. namespace Km.Utils.Helpers
  11. {
  12. /* 说明
  13. * 注:
  14. * 编写锁步骤说明:
  15. * 1、编写对应类继承LockExt
  16. * 2、编写属性如下
  17. * public static ILockExt Instance
  18. {
  19. get
  20. {
  21. LockOfTable l = new LockOfTable();
  22. l.LockFormate = "BillTableLock({0})";
  23. return l;
  24. }
  25. }
  26. *
  27. * 使用锁说明:
  28. * 1、快捷使用如下
  29. * //排队获得锁
  30. * using (LockOfTable.Instance.EnterLock("台位号"))
  31. * {
  32. * //你的操作
  33. * }
  34. * //尝试获得锁
  35. * bool blnLockTaken = false;
  36. * using (LockOfTable.Instance.TryEnterLock("台位号", ref blnLockTaken))
  37. * {
  38. * if (!blnLockTaken)
  39. * {
  40. * //台位已被锁定
  41. * return;
  42. * }
  43. * //你的操作
  44. * }
  45. *
  46. * 2、普通使用如下(更多的控制,但是要手动调用Exit进行释放锁)
  47. * LockOfTable tableLock = LockOfTable.Instance;
  48. * tableLock.Enter("台位号");
  49. * tableLock.Pulse("台位号");
  50. * tableLock.Wait("台位号");
  51. * tableLock.Exit("台位号");
  52. * ...
  53. */
  54.  
  55. #region 台位锁
  56. /// <summary>
  57. /// 功能描述:台位锁
  58. ////// 创建日期:2018-06-07 11:30:45
  59. ////// </summary>
  60. public class LockOfTable : LockExt
  61. {
  62. public static ILockExt Instance
  63. {
  64. get
  65. {
  66. LockOfTable l = new LockOfTable();
  67. l.LockFormate = "BillTableLock({0})";
  68. return l;
  69. }
  70. }
  71. }
  72. #endregion
  73.  
  74. #region 出品单锁
  75. /// <summary>
  76. /// 功能描述:出品单锁
  77. ////// 创建日期:2018-06-07 11:35:56
  78. ////// </summary>
  79. public class LockOfBill0 : LockExt
  80. {
  81. public static ILockExt Instance
  82. {
  83. get
  84. {
  85. LockOfTable l = new LockOfTable();
  86. l.LockFormate = "Bill0Lock({0})";
  87. return l;
  88. }
  89. }
  90. }
  91. #endregion
  92. }

使用

  1. using (LockOfTable.Instance.EnterLock(""))
  2. {
  3. Console.WriteLine("enter:" + i);
  4. Console.WriteLine(i);
  5. Thread.Sleep();
  6. }

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. Vue中this的绑定

    之前写过一篇文章 ES6与React中this完全解惑 其实Vue也是相同的道理.在Vue的官方文档中提到: 不要在选项属性或回调上使用箭头函数,比如 created: () => consol ...

  2. Windows下快速搭建安卓开发环境android-studio

    Windows下快速搭建安卓开发环境android-studio 发布时间:2018-01-18 来源:网络 上传者:用户 关键字: 安卓 搭建 Android Windows 快速 环境 Studi ...

  3. Linux虚拟文件系统(VFS)学习

    虚拟文件系统(Virtual Filesystem)也可称之为虚拟文件系统转换(Virtual Filesystem Switch),是一个内核软件层,用来处理与Unix标准文件系统相关的全部系统调用 ...

  4. 报错:javax.servlet.jsp.PageContext cannot be resolved to a type;javax.servlet.jsp.JspException cannot be resolved to a type

    Multiple annotations found at this line: - javax.servlet.jsp.PageContext cannot be resolved to a typ ...

  5. &lt;模拟电子学习1&gt;Multisim 12.0 结构和仿真51最小的单芯片系统

    周围环境: 系统环境: win7 64位置 软件平台:Multisim 12.0 目的: 刚毕业,可是模电知识也忘得差点儿相同了,加之自己想搞搞硬件设计.假设仅仅是看模电书.不实践,还是终觉浅.当做兴 ...

  6. 百度地图API二:根据标注点坐标范围计算显示缩放级别zoom自适应显示地图

    原文:百度地图API二:根据标注点坐标范围计算显示缩放级别zoom自适应显示地图 版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/liusaint1992/ ...

  7. tornado+ansible+twisted+mongodb操作和维护系统开发自己主动(一个)

    前段时间去了解ansible配置管理(http://blog.csdn.net/column/details/ansible.html   anisble配置工具盒翻译),我感觉很强烈,认为短期内to ...

  8. Python+Django+SAE系列教程10-----Django模板

    在本章中,我们开始模板,在前面的章节,您可能已经注意到,我们回到文本的方式有点特别的示例视图. 那.HTML直接在硬编码 Python 其中代码. 这的确是一个小BT. def current_dat ...

  9. NPM镜像设置方法!

    使用npm安装一些包失败了的看过来(npm国内镜像介绍) 发布于 2012-4-26 04:19 最后一次编辑是 2013-12-11 23:21 这个也是网上搜的,亲自试过,非常好用! 镜像使用方法 ...

  10. ObjectDataProvider

    <Window.Resources> <ObjectDataProvider x:Key="personList" ObjectType="{x:Typ ...