如果没有静态字段,我是否需要担心对象是线程安全的?

Bre*_*ner 2 c# singleton dependency-injection thread-safety

我正在写一个装饰器来实现缓存.该对象将由我的DI容器注册为单例.因为我知道我将对象注册为单例,所以表示我的缓存的字段不是静态的.我不确定这是否是最佳做法,但我试图不惜一切代价避免锁定.我的缓存是懒惰的初始化,只有一次昂贵/运行.我的问题是我需要担心运行缓存初始化逻辑的多个线程吗?我的直觉告诉我"是的,我确实需要担心",但我听到其他开发人员说"如果它不是静止的话就没有锁定点".

//SimpleInjector DI Container configuration
public static class Bootstrapper
{
    public static void ConfigureContainer(Container container)
    {
        container.Register<IQueryHandler<GetFoos, Foo[]>, GetFoosHandler>(Lifestyle.Singleton);
        container.RegisterDecorator<IQueryHandler<GetFoos, Foo[]>, GetFoosCachingHandler>(Lifestyle.Singleton);
    }
}

public class Foo
{
    public int Id;
    public string FooTypeCode;
    public string Name;
}

public class GetFoos : IQuery<Foo[]>
{
    public string FooTypeCode;
}

public class GetFoosCachingHandler : IQueryHandler<GetFoos, Foo[]>
{
    private Lazy<Dictionary<string, Foo[]>> _cache;

    private readonly IQueryHandler<GetFoos, Foo[]> _queryHandler;

    public GetFoosCachingHandler(IQueryHandler<GetFoos, Foo[]> queryHandler)
    {
        _queryHandler = queryHandler;

        _cache = new Lazy<Dictionary<string, Foo[]>>(() =>
        {
            //expensive and run only once operation e.g. subscribe to bus for cache invalid messages and reset cache

            return new Dictionary<string, Foo[]>();
        });
    }

    public Foo[] Handle(GetFoos query)
    {
        var cache = _cache.Value;

        if (!cache.ContainsKey(query.FooTypeCode))
        {
            cache[query.FooTypeCode] = _queryHandler.Handle(new GetFoos { FooTypeCode = query.FooTypeCode });
        }

        return cache[query.FooTypeCode];
    }
}
Run Code Online (Sandbox Code Playgroud)

Guf*_*ffa 5

是的,您需要锁定以防止多个线程运行相同的代码.

"如果它不是静态的,那么锁定没有意义"

这仅适用于每个线程都有自己的类实例时.只要在线程之间共享实例,就需要同步访问权限.