前言:
在系統中多少會遇到某些交易間需要互斥(不然容易造成DeadLock
).
在我們當前系統中有許多動作間需要互斥,不然會有DeadLock問題
藉由已經分析DeadLock Report後,我開始構思如何讓建立Lock可以變得更容易且好理解.
所以就建構出此Lock架構.
如何在此框架使用Lock機制
我們只需要做幾個步驟:
- 在使用Lock類別上掛
LockerInterceptor
攔截器標籤. - 使用Lock方法上使用
LockAttribute
標籤[Lock(LockKey = "Your lock Key")]
(Key
屬性是必填的) - 設定Lock屬性.
Redlock.Net
.使用方法如下,這樣在多執行緒系統中MethodA1
跟MethodB_A
就不會有同時執行問題,這樣就可以造成這兩個動作互斥.
[Intercept(typeof(LockerInterceptor))]
public class LockerContext : ILockerContext
{
[Lock(Key = "A")]
public virtual void MethodA1()
{
Thread.Sleep(5);
Console.WriteLine($"{DateTime.Now:HH:mm:ss fff} MethodA1 Done");
Thread.Sleep(5);
}
[Lock(Key = "A")]
public virtual void MethodB_A()
{
Thread.Sleep(5);
Console.WriteLine($"{DateTime.Now:HH:mm:ss fff} MethodB_A Done");
Thread.Sleep(5);
}
}
架構解說
我是使用ReaderWriterLockSlim
因為支援ReadLock不互斥,WriteLock互斥邏輯
我是如何讓使用者輸入Key
來建立不同lock呢?
Key
都有不同Lock
物件LockAttribute
LockAttribute
有幾個屬性.
Key
:鎖名稱Mode
:鎖的模式LockMode.XLock
:獨占鎖會排斥其他資源請求此鎖,須等待資源釋放.LockMode.Shared
:Shared lock之間不互斥.
Order
:因為支援多個LockAttribute
,此屬性決定執行此方法前要求鎖順序
LockerInterceptor
我們直接來IInterceptor
物件最核心邏輯方法Intercept(IInvocation invocation)
.
利用GetCustomAttributes
取得方法上所有LockAttribute
並在方法執行前要求拿到,所需要Lock
資源才可以執行方法,最後在finally
時釋放lock資源
public void Intercept(IInvocation invocation)
{
var methodName = invocation.Method.Name;
var lockAttributes = invocation.Method.GetCustomAttributes(typeof(LockAttribute), true) as LockAttribute[];
if (IsMarkLockLockAttribute(lockAttributes))
{
var lockProviders = GetLockProviders(lockAttributes);
try
{
foreach (var lockProvider in lockProviders)
{
lockProvider.AddLock();
}
invocation.Proceed();
}
catch (Exception e)
{
_log.Exception("Something wrong!", e);
throw e;
}
finally {
foreach (var lockProvider in lockProviders)
{
lockProvider.ReleaseLock();
}
_log.Info($"{DateTime.Now:HH:mm:ss fff} {methodName} Release Lock");
}
}
else
{
invocation.Proceed();
}
}
SampleCode
我利用Nunit寫一個簡單程式Print在console讓我們方便觀看結果.
MethodA
:Shared lock mode on key AMethodA1
:X lock mode on key AMethodB_A
:X lock mode on key A and BMethodB
:X lock mode on key B
理論上MethodB
只會對於MethodB_A
互斥,MethodB
並不會跟MethodA
,MethodA1
有互斥反應.
Result
我們發現MethodB_A
這個方法會對於,所有key是A
,B
方法互斥,MethodA
則不會對於MethodA
,MethodB
互斥.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
14:26:59 815 MethodA1 Done 14:26:59 816 MethodB Done 14:26:59 919 MethodA1 Release Lock 14:26:59 920 MethodB Release Lock 14:27:00 020 MethodB Done 14:27:00 120 MethodB Release Lock 14:27:00 220 MethodB_A Done 14:27:00 320 MethodB_A Release Lock 14:27:00 420 MethodA1 Done 14:27:00 520 MethodA1 Release Lock 14:27:00 620 MethodB_A Done 14:27:00 720 MethodB_A Release Lock 14:27:00 820 MethodB Done 14:27:00 820 MethodA1 Done 14:27:00 920 MethodB Release Lock 14:27:00 920 MethodA1 Release Lock 14:27:01 020 MethodB_A Done 14:27:01 120 MethodB_A Release Lock 14:27:01 220 MethodB_A Done 14:27:01 320 MethodB_A Release Lock 14:27:01 420 MethodB Done 14:27:01 420 MethodA1 Done 14:27:01 520 MethodB Release Lock 14:27:01 520 MethodA1 Release Lock 14:27:01 620 MethodA Done 14:27:01 620 MethodA Done 14:27:01 620 MethodA Done 14:27:01 620 MethodA Done 14:27:01 620 MethodA Done 14:27:01 720 MethodA Release Lock 14:27:01 720 MethodA Release Lock 14:27:01 720 MethodA Release Lock 14:27:01 720 MethodA Release Lock 14:27:01 720 MethodA Release Lock 14:27:01 820 MethodB Done 14:27:01 920 MethodB Release Lock 14:27:02 020 MethodB Done 14:27:02 120 MethodB Release Lock 14:27:02 220 MethodB_A Done 14:27:02 320 MethodB_A Release Lock 14:27:02 420 MethodA1 Done 14:27:02 520 MethodA1 Release Lock 14:27:02 620 MethodB_A Done 14:27:02 720 MethodB_A Release Lock 14:27:02 820 MethodB_A Done 14:27:02 920 MethodB_A Release Lock 14:27:03 020 MethodA1 Done 14:27:03 020 MethodB Done 14:27:03 120 MethodA1 Release Lock 14:27:03 120 MethodB Release Lock 14:27:03 220 MethodA1 Done 14:27:03 220 MethodB Done 14:27:03 320 MethodA1 Release Lock 14:27:03 320 MethodB Release Lock 14:27:03 420 MethodB_A Done 14:27:03 520 MethodB_A Release Lock 14:27:03 620 MethodA1 Done 14:27:03 720 MethodA1 Release Lock 14:27:03 820 MethodB_A Done 14:27:03 920 MethodB_A Release Lock 14:27:04 020 MethodA1 Done 14:27:04 020 MethodB Done 14:27:04 120 MethodA1 Release Lock 14:27:04 120 MethodB Release Lock 14:27:04 220 MethodA Done 14:27:04 220 MethodA Done 14:27:04 220 MethodA Done 14:27:04 220 MethodA Done 14:27:04 320 MethodA Release Lock 14:27:04 320 MethodA Release Lock 14:27:04 320 MethodA Release Lock 14:27:04 320 MethodA Release Lock 14:27:04 420 MethodB Done 14:27:04 520 MethodB Release Lock 14:27:04 620 MethodB_A Done 14:27:04 720 MethodB_A Release Lock 14:27:04 820 MethodA1 Done 14:27:04 920 MethodA1 Release Lock 14:27:05 020 MethodA Done 14:27:05 120 MethodA Release Lock |
小結
本篇主要想要介紹使用Lock機制.
利用ReaderWriterLockSlim就可以建立如DB lock,實在非常方便.
假如想要細部了解Autofac + Interceptors(AOP) 動態代理可以參考我之前寫文章,這裡我就不多敘述了.
如果本文對您幫助很大,可街口支付斗內鼓勵石頭^^