From eea309c1338ab5b5100c76ac9fb6a800f7a2d04c Mon Sep 17 00:00:00 2001 From: Soar360 Date: Tue, 3 Sep 2024 10:40:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20KeyedLocker=20=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E9=94=81=E5=AD=97=E7=AC=A6=E4=B8=B2=E9=80=A0=E6=88=90?= =?UTF-8?q?=E7=9A=84=E9=94=81=E5=AE=9A=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- XCode/Common/KeyedLocker.cs | 29 +++++++++++++++++++++++++++++ XCode/Entity/Entity.cs | 6 ++---- 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 XCode/Common/KeyedLocker.cs diff --git a/XCode/Common/KeyedLocker.cs b/XCode/Common/KeyedLocker.cs new file mode 100644 index 000000000..99a45da5a --- /dev/null +++ b/XCode/Common/KeyedLocker.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace XCode.Common; + +/// +/// 基于键的锁定器 +/// +internal class KeyedLocker +{ + private static object[] Lockers; + static KeyedLocker() + { + int Length = 8; + var temp = new object[Length]; + for (int i = 0; i < Length; i++) temp[i] = new object(); + Lockers = temp; + } + + public static object SharedLock(string key) + { + if (key is null) throw new ArgumentNullException(nameof(key)); + var code = key.GetHashCode(); + return Lockers[Math.Abs(code % Lockers.Length)]; + } +} diff --git a/XCode/Entity/Entity.cs b/XCode/Entity/Entity.cs index 497d8ab00..72022e9b5 100644 --- a/XCode/Entity/Entity.cs +++ b/XCode/Entity/Entity.cs @@ -2046,8 +2046,7 @@ public static TEntity GetOrAdd(TKey key, Func fin if (entity != null) return entity; // 加锁,避免同一个key并发新增 - var keyLock = $"{typeof(TEntity).FullName}-{key}"; - lock (keyLock) + lock (KeyedLocker.SharedLock(key!.ToString())) { // 打开事务,提升可靠性也避免读写分离造成数据不一致 using var trans = Meta.CreateTrans(); @@ -2096,8 +2095,7 @@ public static TEntity GetOrAdd(TKey key, Func find, Func.SharedLock(key!.ToString())) { // 打开事务,提升可靠性也避免读写分离造成数据不一致 using var trans = Meta.CreateTrans();