【问题标题】:Does my IBackingStore need to be thread safe?我的 IBackingStore 是否需要线程安全?
【发布时间】:2010-11-06 11:58:54
【问题描述】:

企业库的文档说:

因为Cache对象的操作方式,保证你 将调用任何后备存储 以单线程方式。这 意味着你不必让你的 实现线程安全。

关于 CacheManager :

通过 CacheManager 对象是线程安全的。

但一个简单的测试证明相反:

这是我的自定义后备存储(只有 Add 方法是相关的)

public class MyStore : IBackingStore
{
    volatile bool isEntered = false;
    #region IBackingStore Members

    public void Add(CacheItem newCacheItem)
    {
        if(isEntered)
            throw new NotImplementedException();
        isEntered = true;

        Thread.Sleep(1000);

        isEntered = false;

    }

    public int Count
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public void Flush()
    {
        throw new NotImplementedException();
    }

    public System.Collections.Hashtable Load()
    {
        return new System.Collections.Hashtable();
    }

    public void Remove(string key)
    {
        throw new NotImplementedException();
    }

    public void UpdateLastAccessedTime(string key, DateTime timestamp)
    {
        throw new NotImplementedException();
    }

    #endregion

    #region IDisposable Members

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    #endregion
}

这是一个通过两个不同线程访问同一个 CacheManager 的测试:

DictionaryConfigurationSource configSource = new DictionaryConfigurationSource();
CacheManagerSettings cacheSettings = new CacheManagerSettings();
configSource.Add(CacheManagerSettings.SectionName, cacheSettings);
CacheStorageData storageConfig = new CacheStorageData("MyStorage", typeof(MyStore));
cacheSettings.BackingStores.Add(storageConfig);
CacheManagerData cacheManagerData = new CacheManagerData("CustomCache", 120, 100, 5, storageConfig.Name);
cacheSettings.CacheManagers.Add(cacheManagerData);
cacheSettings.DefaultCacheManager = cacheManagerData.Name;


CacheManagerFactory cacheFactory = new CacheManagerFactory(configSource);
ICacheManager cacheManager = cacheFactory.CreateDefault();
Thread thread = new Thread(() =>
{
    cacheManager.Add("item1", "odaiu");
});
thread.Start();
cacheManager.Add("item2", "dzaoiudoiza");

Add 方法在两个不同的线程中执行两次(因为它抛出了 Add 方法的“NotImplementedException”)。

是我的代码有问题还是企业库的文档有问题?

【问题讨论】:

    标签: .net caching enterprise-library


    【解决方案1】:

    由于文档对此非常明确,我会相信文档。

    您的证明存在缺陷,因为您正在为该类创建一个明确的多线程用例。使其线程安全的特定接口没有什么固有的。所以这肯定会失败。

    企业库保证他们将以线程安全的方式管理接口。在内部,他们会注意管理类的线程安全。

    注意:我没有关于这个库的任何具体知识,但是有明确的文档,我会相信它。

    【讨论】:

      【解决方案2】:

      我同意 JaredPar 的观点,即文档声明访问是同步的,因此是安全的。但是,如果您查看用于实现交付的后备存储的源代码,您会发现它被编码为期望在多线程环境中运行。所以也许这是一个陈旧文档的例子。

      以下摘录来自 EntLib 5.0 中的 IsolatedStorageBackingStore,认为 4.1 的实现是相同的。为清楚起见,摘录只是一种方法,但对底层 IsolatedStorageFile 的所有访问都被锁定。

      /// <summary>
      /// Adds new item to persistence store
      /// </summary>
      /// <param name="storageKey">Unique key for storage item</param>
      /// <param name="newItem">Item to be added to cache. May not be null.</param>
      protected override void AddNewItem(int storageKey, CacheItem newItem)
      {
          lock (store)
          {
              string storageLocation = GenerateItemLocation(storageKey);
              IsolatedStorageCacheItem cacheItem =
                  new IsolatedStorageCacheItem(store, storageLocation, this.encryptionProvider);
              cacheItem.Store(newItem);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-05-08
        • 2013-12-07
        • 2016-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-19
        • 2016-11-02
        相关资源
        最近更新 更多