条件同步,锁定

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了条件同步,锁定相关的知识,希望对你有一定的参考价值。

我有一个问题,关于如何在阅读时不会锁定的方式实现列表/字典,并在写入时锁定。我的代码来自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>字段,而不是我希望任何调用缓存检查键的存在值,但写入它将锁定和挂起任何读取,直到该值写入字典

使用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;
 }   
}
答案

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

您需要进行配置以确认此实现比您当前的实现更快/更慢。

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");
        }
    }
}

以上是关于条件同步,锁定的主要内容,如果未能解决你的问题,请参考以下文章

线程同步——条件变量

线程基础四 使用Monitor类锁定资源

四十Linux 线程——线程同步之条件变量

Linux系统编程—线程—线程条件控制实现线程的同步

适当使用同步或锁定一段代码

如何在不锁定活动方向的情况下锁定片段方向?