1

我创建了一个CachedRepository如下所示的泛型:

public class CachedRepository<T> : ICachedRepository, IRepository<T> where T : BaseModel, new()
{
        private static readonly Lock<T> TypeLock = new Lock<T>();

        public void DeleteBatch(IQueryable<T> entities)
        {
            lock (TypeLock)
            {
                // delete logic here
            }
        }

        public T GetNoTracking(int id)
        {
            lock (TypeLock)
            {
                // fetch by id logic here
            }
        }
}

通过使用通用对象来锁定,我将获得每种类型的锁定(即处理不同类型的线程不会一个接一个地等待)。但是,此类用于很少更改但读取量很大的对象列表,因此使用简单锁定lock将延迟读取器,直到另一个读取器完成。

我查看了ReaderWriterLockSlim,但它不是通用类,如果我使用它,我会失去我现在拥有的类型锁定。

问题:如何在保持lock(generic_type_instance)模式提供的类型锁定的同时减少对读者的锁定?

4

2 回答 2

4

不需要是通用的。包含对象的类是泛型的,因此对于CachedRepository已经输入的每个泛型类型,它都会有不同的静态变量,而不管静态对象是否也是泛型的。只需使用常规ReaderWriterLockSlim作为静态变量,您的代码就可以正常工作。

于 2017-09-22T13:26:34.660 回答
0

注意: @Servy 是绝对正确的。示例中的这种抽象只是您的场景的开销。

您可以将 ReaderWriterLockSlim 包装到一个泛型类中。公开 ReaderWriterLockSlim 的读写锁的 Enter、Exit 方法,以便能够正确使用它。

只是一个样本:

        internal class ReaderFreadlyLock<T>
        {
            private readonly ReaderWriterLockSlim lck = new ReaderWriterLockSlim();

            public T Read(Func<T> func)
            {
                this.lck.EnterReadLock();
                try
                {
                    return func();
                }
                finally
                {
                    this.lck.ExitReadLock();
                }
            }

            public void Write(Action action)
            {

                this.lck.EnterReadLock();
                try
                {
                    action();
                }
                finally
                {
                    this.lck.ExitWriteLock();
                }
            }
        }

然后你可以像这样使用它:

var chached = TypeLock.Read(() => {
    // read from cache 
});


TypeLock.Write(() => {    
    // write to db    
    // write to cache 
});
于 2017-09-22T13:22:40.130 回答