【问题标题】:Should wrapping a thread safe object be sufficient to ensure thread safety?包装线程安全对象是否足以确保线程安全?
【发布时间】:2019-11-21 10:44:36
【问题描述】:

我想将对 ASP.Net MemoryCache 的调用封装在一个适用于业务类型的类中。

这是我写的:

public interface IMyModelStore 
{
    MyModel RetrieveMyModel(Guid id);
    void StoreMyModel(MyModel obj);
}

public sealed class InMemoryCache : IMyModelStore
{
    public static  InMemoryCache Instance { get; } = new InMemoryCache(TimeSpan.FromMinutes(30));

    private readonly TimeSpan _expiration;

    private readonly CacheItemPolicy _cachePolicy;

    private InMemoryCache(TimeSpan expiration)
    {
        this._expiration = expiration;
        _cachePolicy = new CacheItemPolicy
        {
            SlidingExpiration = _expiration 
        };
    }

    public RetrieveMyModel(Guid id)
    {
        if (id == Guid.Empty) throw new ArgumentOutOfRangeException(nameof(id));

        return (MyModel)MemoryCache.Default.Get(id.ToString());
    }

    public void StoreMyModel(MyModel obj)
    {
        MemoryCache.Default.Add(obj.Id.ToString(), obj, _cachePolicy);
    }
}

我的感觉是我不必处理线程安全问题,因为我的代码只是获取数据并将数据传递给线程安全的 MemoryCache。

我说的对吗?

我想,唯一可能导致麻烦的情况是,当一个线程调用 RetrieveMyModel 的同时另一个线程使用相同的 ID 调用 StoreMyModel。

【问题讨论】:

  • 您的InMemoryCache 本身是线程安全的。正如您所指出的,可能还有其他种族具有不同的线程同时操纵MyModel
  • 谢谢@canton7。我稍微改写了最后一句话。你的cmets表明我不清楚。我不是在谈论 MyModel 对象的线程安全性。
  • 为此,您必须查看MemoryCache 的行为方式。你的类和MemoryCache 一样是线程安全的,没有更好,也没有更差。
  • 有一个潜在风险的事情。 MemoryCache.Default 的实现由于某种原因使用了不完全线程安全的双重检查锁定模式,因此在可以从不同线程调用此属性的代码中使用 MemoryCache.Default 不是线程安全的。

标签: c# multithreading thread-safety


【解决方案1】:

您的课程是线程安全的(目前)。无需增加复杂性即可确保线程安全。

我想,唯一可能导致麻烦的情况是,当一个线程调用 RetrieveMyModel 的同时另一个线程使用相同的 ID 调用 StoreMyModel。

RetrieveMyModelStoreMyModel 是线程安全的,一些线程可以使用相同的 id 调用此方法而没有风险。只是RetrieveMyModel的返回将取决于执行的顺序。

【讨论】:

    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 1970-01-01
    • 2012-08-21
    • 2018-12-07
    • 2011-08-13
    相关资源
    最近更新 更多