Lock only on an Id

前端 未结 4 642
醉梦人生
醉梦人生 2021-01-18 14:31

I have a method which needs to run exclusivley run a block of code, but I want to add this restriction only if it is really required. Depending on an Id value (an Int32) I w

4条回答
  •  一个人的身影
    2021-01-18 15:27

    I used the following approach. Do not check the original ID, but get small hash-code of int type to get the existing object for lock. The count of lockers depends on your situation - the more locker counter, the less the probability of collision.

    class ThreadLocker
    {
        const int DEFAULT_LOCKERS_COUNTER = 997;
        int lockersCount;
        object[] lockers;
    
        public ThreadLocker(int MaxLockersCount)
        {
            if (MaxLockersCount < 1) throw new ArgumentOutOfRangeException("MaxLockersCount", MaxLockersCount, "Counter cannot be less, that 1");
            lockersCount = MaxLockersCount;
            lockers = Enumerable.Range(0, lockersCount).Select(_ => new object()).ToArray();
        }
        public ThreadLocker() : this(DEFAULT_LOCKERS_COUNTER) { }
    
        public object GetLocker(int ObjectID)
        {
            var idx = (ObjectID % lockersCount + lockersCount) % lockersCount;
            return lockers[idx];
        }
        public object GetLocker(string ObjectID)
        {
            var hash = ObjectID.GetHashCode();
            return GetLocker(hash);
        }
        public object GetLocker(Guid ObjectID)
        {
            var hash = ObjectID.GetHashCode();
            return GetLocker(hash);
        }
    }
    

    Usage:

    partial class Program
    {
        static ThreadLocker locker = new ThreadLocker();
        static void Main(string[] args)
        {
            var id = 10;
            lock(locker.GetLocker(id))
            {
    
            }
        }
    }
    

    Of cource, you can use any hash-code functions to get the corresponded array index.

提交回复
热议问题