【问题标题】:ContainsKey Thread SafeContainsKey 线程安全
【发布时间】:2010-10-17 04:15:57
【问题描述】:

在以下代码中:

public class StringCache
{
    private readonly object lockobj = new object();

    private readonly Dictionary<int, string> cache = new Dictionary<int, string>();

    public string GetMemberInfo(int key)
    {
        if (cache.ContainsKey(key))
            return cache[key];
        lock (lockobj)
        {
            if (!cache.ContainsKey(key))
                cache[key] = GetString(key);
        }
        return cache[key];
    }

    private static string GetString(int key)
    {
        return "Not Important";
    }
}

1) ContainsKey 线程安全吗? IOW,如果在另一个线程向字典中添加内容时正在执行该方法会发生什么? 2)第一次返回cache[key],有没有可能返回乱码?

TIA,

MB

【问题讨论】:

    标签: c# multithreading dictionary


    【解决方案1】:

    ContainsKey 的固有线程安全无关紧要,因为 ContainsKey 和 cache[key] 之间没有同步。

    例如:

    if (cache.ContainsKey(key))
       // Switch to another thread, which deletes the key.
       return cache[key];
    

    MSDN 在这一点上非常清楚:

    允许访问集合 通过多个线程进行阅读和 写,你必须实现你自己的 同步。

    如需了解更多信息,JaredPar 在http://blogs.msdn.com/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx 上发布了一篇关于线程安全集合的精彩博文。

    【讨论】:

      【解决方案2】:

      不,如果您在尝试读取时写入值,则 ContainsKey 不是线程安全的。

      是的,您有可能获得无效结果,但您可能会首先看到异常。

      看看 ReaderWriterLockSlim 在这种情况下的锁定 - 它是为做这种事情而构建的。

      【讨论】:

        【解决方案3】:

        这是MSDN documentation:中的内容

        这种类型的公共静态(在 Visual Basic 中为共享)成员是线程安全的。不保证任何实例成员都是线程安全的。

        字典)>) 可以支持多个阅读器 同时,只要 集合未修改。即使是这样, 通过集合枚举是 本质上不是线程安全的 程序。在极少数情况下 枚举与写竞争 访问,集合必须是 在整个枚举期间锁定。 允许访问集合 通过多个线程进行阅读和 写,你必须实现你自己的 同步。

        如果我没看错的话,我不相信它是线程安全的。

        【讨论】:

          【解决方案4】:

          字典不是线程安全的

          如果你这么说

          如果该方法是 在另一个线程运行时执行 向字典中添加内容?

          那么我想其他函数也可以访问cache。您需要同步对cache 的访问(读取和写入)。在所有这些操作中使用您的锁定对象。

          【讨论】:

            【解决方案5】:

            我相信它不是线程安全的,

            我建议通过下面的链接,它显示了线程安全字典的实现,或者最好开发自己的同步。

            http://lysaghtn.weebly.com/synchronised-dictionary.html

            【讨论】:

            • 找不到链接 (404)。
            猜你喜欢
            • 1970-01-01
            • 2022-11-21
            • 1970-01-01
            • 2021-07-12
            • 2011-03-30
            • 1970-01-01
            • 1970-01-01
            • 2012-09-03
            • 2011-08-01
            相关资源
            最近更新 更多