LockManager.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. using System.Collections.Concurrent;
  2. using WingServerCommon.Log;
  3. namespace WingServerCommon.Utilities
  4. {
  5. public class LockManager
  6. {
  7. private bool _isDistributed = false;
  8. private static object _acquireLocker = new object();
  9. private ConcurrentDictionary<string, ILocker> _lockers = new ConcurrentDictionary<string, ILocker>();
  10. public LockManager()
  11. {
  12. _isDistributed = false;
  13. Logger.WriteLineInfo($"LockManager init success, mode: Alone");
  14. }
  15. public LockManager(Func<string, bool> OnGetLock, Func<string, bool> OnReleaseLock)
  16. {
  17. _isDistributed = true;
  18. DistributedLock.OnGetLock = OnGetLock;
  19. DistributedLock.OnReleaseLock = OnReleaseLock;
  20. Logger.WriteLineInfo($"LockManager init success, mode: Distributed");
  21. }
  22. public async Task<ILocker> Acquire(string lockKey)
  23. {
  24. Logger.WriteLineInfo($"LockManager Acquire locker by key:{lockKey}");
  25. ILocker locker;
  26. if (!_lockers.TryGetValue(lockKey, out locker))
  27. {
  28. lock (_acquireLocker)
  29. {
  30. locker = _lockers.GetOrAdd(lockKey, (k) =>
  31. {
  32. if (_isDistributed)
  33. {
  34. return new DistributedLock(lockKey);
  35. }
  36. else
  37. {
  38. return new StandAloneLock(lockKey);
  39. }
  40. });
  41. }
  42. }
  43. return await locker.LockAsync();
  44. }
  45. public void Release(string lockKey)
  46. {
  47. Logger.WriteLineInfo($"LockManager Release locker by key:{lockKey}");
  48. if (_lockers.TryGetValue(lockKey, out ILocker locker))
  49. {
  50. locker.Dispose();
  51. }
  52. }
  53. }
  54. public interface ILocker : IDisposable
  55. {
  56. Task<ILocker> LockAsync();
  57. }
  58. public class StandAloneLock : ILocker
  59. {
  60. SemaphoreSlim slimlock = new SemaphoreSlim(1, 1);
  61. private string _lockKey;
  62. private string _serialNumber;
  63. public StandAloneLock(string guid)
  64. {
  65. _lockKey = guid;
  66. }
  67. public async Task<ILocker> LockAsync()
  68. {
  69. await slimlock.WaitAsync(3 * 1000);
  70. _serialNumber = Guid.NewGuid().ToString("N");
  71. Logger.WriteLineInfo($"LockManager StandAloneLock waitasync end, lockkey:{_lockKey}, serialNumber:{_serialNumber}");
  72. return this;
  73. }
  74. public void Dispose()
  75. {
  76. slimlock.Release();
  77. Logger.WriteLineInfo($"LockManager StandAloneLock release end, lockkey:{_lockKey}, serialNumber:{_serialNumber}");
  78. }
  79. }
  80. public class DistributedLock : ILocker
  81. {
  82. public static Func<string, bool> OnGetLock;
  83. public static Func<string, bool> OnReleaseLock;
  84. private string _lockKey;
  85. private string _serialNumber;
  86. public DistributedLock(string guid)
  87. {
  88. _lockKey = guid;
  89. }
  90. public async Task<ILocker> LockAsync()
  91. {
  92. OnGetLock.Invoke(_lockKey);
  93. _serialNumber = Guid.NewGuid().ToString("N");
  94. Logger.WriteLineInfo($"LockManager DistributedLock waitasync end, lockkey:{_lockKey}, serialNumber:{_serialNumber}");
  95. return this;
  96. }
  97. public void Dispose()
  98. {
  99. OnReleaseLock.Invoke(_lockKey);
  100. Logger.WriteLineInfo($"LockManager DistributedLock release end, lockkey:{_lockKey}, serialNumber:{_serialNumber}");
  101. }
  102. }
  103. }