多线程访问字典

祝你好运

我已经在网络上搜索,我得到一个有点困惑的多线程(lockMonitor.Entervolatile等),而不是要求的解决方案在这里,我已经试过一些“自制”关于多线程的管理,我想有你的意见。

这是我的上下文:

- 我有一个包含静态的静态类 Dictionary<int,string>

-我有很多的任务(假设1000)阅读本Dictionary每秒钟

-我有一个另一项任务,即会更新这个Dictionary每10s。

这是缓存的代码:

public static class Cache
{
    public static bool locked = false;
    public static Dictionary<int, string> Entries = new Dictionary<int, string>();
    public static Dictionary<int, string> TempEntries = new Dictionary<int, string>();

    // Called by 1000+ Tasks
    public static string GetStringByTaskId(int taskId)
    {
        string result;

        if (locked)
            TempEntries.TryGetValue(taskId, out result);
        else
            Entries.TryGetValue(taskId, out result);

        return result;
    }

    // Called by 1 task
    public static void UpdateEntries(List<int> taskIds)
    {
        TempEntries = new Dictionary<int, string>(Entries);

        locked = true;
        Entries.Clear();

        try
        {
            // Simulates database access
            Thread.Sleep(3000);

            foreach (int taskId in taskIds)
            {
                Entries.Add(taskId, $"task {taskId} : {DateTime.Now}");
            }
        }
        catch (Exception ex)
        {
            Log(ex);
        }
        finally
        {
            locked = false;
        }
    }
}

这是我的问题:

程序运行,但我不明白为什么方法中的两次“锁定”bool赋值UpdateEntries不会产生多线程异常,因为它被另一个线程“每次”读取

有没有更传统的方法来处理这个问题,我觉得这是一种奇怪的方法?

约翰吴

处理此问题的传统方法是使用ConcurrentDictionary此类是线程安全的,设计用于多个线程对其进行读写。您仍然需要注意潜在的逻辑问题(例如,如果必须同时添加两个键才能让其他线程看到它们中的任何一个),但是对于大多数操作而言,无需额外锁定就可以了。

针对您的特定情况处理此问题的另一种方法是使用普通字典,但一旦它可供读者线程使用,就将其视为不可变的。这将更有效,因为它避免了锁定。

public static void UpdateEntries(List<int> taskIds)
{
    //Other threads can't see this dictionary
    var transientDictionary = new Dictionary<int, string>();  

    foreach (int taskId in taskIds)
    {
        transientDictionary.Add(taskId, $"task {taskId} : {DateTime.Now}");
    }

    //Publish the new dictionary so other threads can see it
    TempEntries = transientDictionary; 
}

一旦字典被分配到TempEntries(其他线程可以访问它的唯一地方),它就永远不会被修改,所以线程问题就消失了。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章