-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 添加AsyncLock的同步版本SyncLock (#572)
- Loading branch information
Showing
5 changed files
with
345 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// ReSharper disable UnusedMember.Global | ||
|
||
namespace EasilyNET.Core.Threading; | ||
|
||
/// <summary> | ||
/// 同步锁,用于仅让一个线程访问共享资源。 | ||
/// </summary> | ||
public sealed class SyncLock | ||
{ | ||
private readonly SyncSemaphore _semaphore = new(); | ||
private int _ownerThreadId = -1; | ||
|
||
/// <summary> | ||
/// 获取内部信号量的占用状态 | ||
/// </summary> | ||
/// <returns></returns> | ||
public int GetSemaphoreTaken() => _semaphore.GetTaken(); | ||
|
||
/// <summary> | ||
/// 获取内部信号量的队列计数 | ||
/// </summary> | ||
/// <returns></returns> | ||
public int GetQueueCount() => _semaphore.GetQueueCount(); | ||
|
||
/// <summary> | ||
/// 锁定,返回一个 <see cref="Release" /> 对象 | ||
/// </summary> | ||
/// <returns></returns> | ||
public Release Lock() | ||
{ | ||
var currentThreadId = Environment.CurrentManagedThreadId; | ||
if (_ownerThreadId == currentThreadId) | ||
{ | ||
throw new InvalidOperationException("Reentrant lock detected"); | ||
} | ||
_semaphore.Wait(); | ||
_ownerThreadId = currentThreadId; | ||
return new(this); | ||
} | ||
|
||
/// <summary> | ||
/// 锁定任务的执行,无返回值 | ||
/// </summary> | ||
/// <param name="action"></param> | ||
public void Lock(Action action) | ||
{ | ||
using var r = Lock(); | ||
action(); | ||
} | ||
|
||
/// <summary> | ||
/// 锁定任务的执行,可返回执行函数的结果 | ||
/// </summary> | ||
/// <param name="action"></param> | ||
public T Lock<T>(Func<T> action) | ||
{ | ||
using var r = Lock(); | ||
return action(); | ||
} | ||
|
||
/// <remarks> | ||
/// Release | ||
/// </remarks> | ||
/// <param name="syncLock"></param> | ||
public readonly struct Release(SyncLock syncLock) : IDisposable | ||
{ | ||
/// <inheritdoc /> | ||
public void Dispose() | ||
{ | ||
syncLock._ownerThreadId = -1; | ||
syncLock._semaphore.Release(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System.Collections.Concurrent; | ||
|
||
namespace EasilyNET.Core.Threading; | ||
|
||
/// <summary> | ||
/// 同步信号量。 | ||
/// </summary> | ||
internal sealed class SyncSemaphore | ||
{ | ||
private readonly ConcurrentQueue<ManualResetEventSlim> _waiters = []; | ||
private int _isTaken; | ||
|
||
/// <summary> | ||
/// 获取是否被占用 | ||
/// </summary> | ||
/// <returns></returns> | ||
public int GetTaken() => _isTaken; | ||
|
||
/// <summary> | ||
/// 获取等待的任务数量 | ||
/// </summary> | ||
/// <returns></returns> | ||
public int GetQueueCount() => _waiters.Count; | ||
|
||
/// <summary> | ||
/// 同步等待 | ||
/// </summary> | ||
public void Wait() | ||
{ | ||
// 如果 _isTaken 的值是 0,则将其设置为 1,并返回。 | ||
if (Interlocked.CompareExchange(ref _isTaken, 1, 0) == 0) | ||
{ | ||
return; | ||
} | ||
// 如果 _isTaken 的值不是 0,创建一个新的 ManualResetEventSlim,并将其设置为未终止状态。 | ||
var mre = new ManualResetEventSlim(false); | ||
// 将 ManualResetEventSlim 实例添加到等待队列中。 | ||
_waiters.Enqueue(mre); | ||
// 等待 ManualResetEventSlim 被终止。 | ||
mre.Wait(); | ||
} | ||
|
||
/// <summary> | ||
/// 释放 | ||
/// </summary> | ||
public void Release() | ||
{ | ||
if (_waiters.TryDequeue(out var toRelease)) | ||
{ | ||
toRelease.Set(); | ||
} | ||
else | ||
{ | ||
Interlocked.Exchange(ref _isTaken, 0); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.