加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 这个示例线程是否安全?

发布时间:2020-12-16 00:04:43 所属栏目:百科 来源:网络整理
导读:假设我有一个充当数据缓存的单例类.多个线程将从缓存中读取,并且单个线程将定期刷新它.它看起来像这样: public sealed class DataStore{ public static DataStore Instance { get { return _instance; } } public DictionaryFoo,Bar FooBar { get; private
假设我有一个充当数据缓存的单例类.多个线程将从缓存中读取,并且单个线程将定期刷新它.它看起来像这样:

public sealed class DataStore
{
    public static DataStore Instance { get { return _instance; } }
    public Dictionary<Foo,Bar> FooBar { get; private set; }

    static DataStore() { }
    private DataStore() { }

    public void Refresh() {
        FooBar = GetFooBarFromDB();
    }

    private static readonly DataStore _instance = new DataStore();
}

我的问题基本上是,当其他线程可能正在访问FooBar时,Refresh()是否安全?我需要使用锁,还是我的获取和设置操作是原子的?我是否需要显式声明volatile字段来备份我的属性?

P.S.,如果有人能想到这个问题的更具描述性的标题,我很乐意欢迎它.

编辑:修复了我的例子来明显纠正非原子代码.

解决方法

是的,在这种情况下你需要显式同步,因为另一个线程可以获得FooBar并在你完成写入之前开始阅读它.

但是,如果你这样做,

public void Refresh() {
    var tmp = new Dictionary<Foo,Bar>();
    // Fill out FooBar from DB
    FooBar = tmp;
}

那么你就不需要添加显式同步,因为从一个引用到另一个引用的切换是原子的.

当然,这里隐含的假设是在Refresh方法之外没有写入.

编辑:您还应该从自动实现的属性切换到手动实现的属性,其中支持变量使用volatile修饰符声明.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读