我的IBackingStore需要线程安全吗?

时间:2009-06-28 13:54:25

标签: .net caching enterprise-library

企业库的文档说:

  

由于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”)。

我的代码或企业库文档有问题吗?

2 个答案:

答案 0 :(得分:0)

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

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

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

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

答案 1 :(得分:0)

我同意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);
    }
}