条件同步,锁定

时间:2018-09-19 10:14:25

标签: c# .net synchronization locking

我有一个问题,关于如何实现列表/字典,使其在阅读时不会锁定而在写入时会锁定。 我来自GitHub项目的代码示例:TextProcessorsCache.cs

/// <summary>
/// Cache of text processors that can be re-used as they do not have
/// state
/// </summary>
public static class TextProcessorsCache
{
    private static readonly ConcurrentDictionary<Type, ITextProcessor> cache;

    static TextProcessorsCache()
    {
        cache = new ConcurrentDictionary<Type, ITextProcessor>();
    }

    public static ITextProcessor GetInstance<T>() where T: class, ITextProcessor, new()
    {
        return cache.GetOrAdd(typeof(T), new T());
    }
}

我想摆脱ConcurrentDictionary<Type,ITextProcessor>字段,而是希望任何缓存调用通过键检查值的存在,但是写入它将锁定并暂停所有读取,直到将值写入字典中< / p>

具有ReaderWriterLock的Impl。

public static class TextProcessorsCache 
{
private static readonly Dictionary<Type, ITextProcessor> cache;
private static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();

static TextProcessorsCache() 
{
  cache = new Dictionary<Type, ITextProcessor>();
}

 public static ITextProcessor GetInstance<T>() where T: class, ITextProcessor, new()
 {
     ITextProcessor processor;
     locker.EnterReadLock();

         cache.TryGetValue(typeof(T), out processor);

     locker.ExitReadLock();

         if (processor == null) 
         {  
              locker.EnterWriteLock();

              if (cache.TryGetValue(typeof(T), out processor))
              {
                   locker.ExitWriteLock();
                   return processor;
              }

              processor = new T();
              cache[typeof(T)] = processor;

              locker.ExitWriteLock();                 
         }
     return processor;
 }   
}

1 个答案:

答案 0 :(得分:0)

一种可能的方法是使用泛型来确保每个实现只实例化一个实例,如下所示。 Cache类将确保仅实例化每个T(类型)中的一个(针对该GetT的所有调用)。

您需要进行分析,以确认此实现比当前实现快/慢。

using System;

namespace Sample
{
    public class Runner
    {
        public static void Main()
        {
            TextProcessorsCache.GetInstance<TextProcessor1>();
            TextProcessorsCache.GetInstance<TextProcessor2>();
            TextProcessorsCache.GetInstance<TextProcessor1>(); // this should not write to the console
            TextProcessorsCache.GetInstance<TextProcessor2>(); // this should not write to the console

            Console.ReadLine();
        }
    }

    public static class TextProcessorsCache
    {
        public static ITextProcessor GetInstance<T>() where T : class, ITextProcessor, new()
        {
            return Cache<T>.Get();
        }
    }

    static class Cache<T> where T : class, ITextProcessor, new()
    {
        internal static T value;
        static Cache()
        {
            value = new T();
        }

        public static T Get()
        {
            return value;
        }
    }

    public interface ITextProcessor
    {
    }

    public class TextProcessor1 : ITextProcessor
    {
        public TextProcessor1()
        {
            Console.WriteLine("1 constructed");
        }
    }

    public class TextProcessor2 : ITextProcessor
    {
        public TextProcessor2()
        {
            Console.WriteLine("2 constructed");
        }
    }
}