首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ConcurrentDictionary与字典

ConcurrentDictionary与字典
EN

Stack Overflow用户
提问于 2022-05-01 05:41:30
回答 1查看 286关注 0票数 0

我不确定这是一个如此简单的问题,正如它在When should I use ConcurrentDictionary and Dictionary?中所述。

在我的例子中,我只有一个线程调用Add来添加项,而有几个线程调用Remove来删除项(每个条目一个,实际上是Timer)。有很多阅读线索。此外,我的逻辑确保被删除的项目不再被使用(基于时间的密钥),即它不会读取它们。

此外,它应该处理一个非常高的输入率。

因此,也许Dictionary在这里更好,因为它具有更好的性能,并且在相同的资源上没有真正的并发写入(我不确定)。毕竟,它不是一个链接列表类型的集合,需要在任何更改时更新项之间的指针。并发AddGet在非线程安全Dictionary的情况下可能是错误的。

换句话说,Add操作是否非原子操作,因为Get操作对于同一密钥的Get操作会返回一个buggy对象,因为Dictionary有一个不稳定的状态?也许只同步Remove操作就足够了?

更新:注意到,我只有一个线程添加了项,几个计时器线程删除了每个项目(必须是一个已经添加的项),而Get操作是对时间范围后面的项目(要删除的项目)执行的而不是操作。另外,单个添加线程会生成一个已添加项的列表,以供处理读取线程读取。这就是为什么我认为它可以在没有任何锁的情况下工作(或者只对删除操作进行锁定)。

EN

回答 1

Stack Overflow用户

发布于 2022-05-01 07:20:07

我认为您可以对此进行优化,以减少字典中的锁数量。关键是找到一个条件来本地化一个时间间隔,在其中您修改字典,并确保在更新字典时不会超出此间隔。

例如,假设您需要10分钟来更新字典。你决定每天10点到11点之间更新字典。你可以在10点完成更新。

然后,从第二天的11:00到10:00,你可以使用你的字典而不加任何锁。在10:00至11:00之间,您必须始终使用锁,因为您的字典可能会更改。

在本例中,不可能在没有锁的情况下修改字典,因为只有在需要更新字典超过1小时时才会发生这种情况。

因此,锁是那个小时内的一个真正的锁,DateTime检查其余的23个小时。我不知道你是否能使你的情况适应这个焦点,但如果你能,你肯定会得到更好的表现。

您可以将此逻辑封装在方法中:

代码语言:javascript
复制
private void DoWithDictionary(Action action)
{
    var now = DateTime.UtcNow;
    if (now.Hour == 10)
    {
        action();
    }
    else
    {
        lock (this._dict)
        {
            action();
        }
    }
}

private T DoWithDictionary<T>(Func<T> action)
{
    var now = DateTime.UtcNow;
    if (now.Hour == 10)
    {
        return action();
    }
    else
    {
        lock (this._dict)
        {
            return action();
        }
    }
}

并使用它:

代码语言:javascript
复制
var keyToGet = 17;
var value = DoWithDictionary(() => this._dict[keyToGet]);

DoWithDictionary(() =>
{
    if (this._dict.TryGetValue(keyToGet, out string text))
    {
        //...
    }
});

var keyToRemove = 17;
DoWithDictionary(() => this._dict.Remove(keyToRemove));

更新

我认为我的回应被误解了。最后,类似于排队更改,每次执行都是在一个批中。

例如,假设一个线程在第一秒钟执行4次删除,在下一秒钟执行2次删除。那条线可以锁6个锁。线程可能有一个列表,其中保存所有人每秒钟删除一次。因此,在第一秒钟,线程添加了4个项。当第二个完成时,线程锁定字典,并仅用一个锁删除4个项。在下一秒中,为这2项删除一个额外的锁。所以,两个锁而不是六个锁。

我认为这是合理的,这是我通常做的,以获得更好的表现。此外,通过数据库访问o套接字发送:添加信息,如果缓冲区已满或过期,则发送所有信息。

这里的问题是,您有很多线程:您可以使用相同的方法,但只能在线程级别获得更好的性能。如果您能够获得一些逻辑(比如我的23/1小时,这只是一个微不足道的示例,在现实世界中使用起来很困难),那么您可以避免所有线程中的锁,从而获得更好的性能。最后,执行锁以获得对资源的独占访问。在我的示例中,我知道我可以在没有锁的情况下访问(而不是修改)字典,而且它是线程安全的,因为我知道(没有真正的锁语句)在这些小时内访问字典是安全的。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72074284

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档