【问题标题】:What will happen in ConcurrentDictionary if there is a collusion on try add and remove?如果在尝试添加和删除时存在串通,ConcurrentDictionary 会发生什么?
【发布时间】:2019-08-14 08:25:17
【问题描述】:

在我的 BL 中,我希望在另一个线程已经在进行中时不执行某个代码。

问题是代码可以(按需求)为每个客户执行一次,但不能为同一客户执行两次

我已经使用 C# ConcurrentDictionary 来跟踪已经在进行中的客户,当执行完成时,我已将它们从 ConcurrentDictionary 中删除,如果我尝试从 @ 中删除客户 ID 会发生什么情况987654324@ 而另一个线程正在尝试添加(相同或不同的键)? ConcurrentDictionary 写锁和try remove 会失败吗?

private static readonly ConcurrentDictionary<int, DateTime> m_customerInProgress = new ConcurrentDictionary<int, DateTime>();

public void ExecuteLogic(int customerId)
{
        if (m_customerInProgress.TryAdd(customerId, DateTime.Now) == false)
        {
            this.Log().Info("customer in progress ");
            return;
        }

        try
        {
            DoSomething();
        }
        catch (Exception ex)
        {
            this.Log().Info("DoSomething failed ");
        }
        finally
        {
            DateTime startDateTime;

            if (m_customerInProgress.TryRemove(customerId, out startDateTime) == false)
            {
                this.Log().Fatal("this should never happens");
            }
            else
            {
                this.Log().Info("customer finished execution");
            }
        }
}

this.Log().Fatal("this should never happens"); 会发生吗?

如果对同一个键同时执行 try add 和 try remove 会发生什么?

如果它针对不同的键执行会发生什么?

【问题讨论】:

  • Code(如果有帮助的话)。
  • 您已经实现了一个可以正常工作的并发锁定机制。 TryAddTryRemove 都是对集合的原子操作。
  • 我的问题是,如果 tryremove 由于 ConcurrentDictionary 锁定的竞争条件而失败,这将导致用户在此功能上死锁(因为他将永远在 ConcurrentDictionary 中),它会发生吗?删除是否会由于比赛条件而失败
  • 只有一个线程会成功添加customerId并继续,最后删除。除非有其他方法可以并行运行并以某种方式删除customerId,否则“这永远不会发生”永远不会发生。

标签: c# multithreading dictionary concurrency


【解决方案1】:

您的代码很好。只有在 TryRemove 完成后,TryAdd 才会成功。

您可能看到的唯一奇怪的事情是,在TryRemove 返回后,线程(我们称之为T1)被挂起,然后另一个线程(我们称之为T2)调用您的方法。它可能会在T1 恢复执行之前执行整个方法,因此您的日志记录可能会交织在一起。

【讨论】:

  • 我的问题是,如果 tryremove 由于 ConcurrentDictionary 锁定的竞争条件而失败,这将导致用户在此功能上死锁(因为他将永远在 ConcurrentDictionary 中),它会发生吗?删除是否会由于比赛条件而失败
  • @eliavra - TryRemove 失败的唯一方法是如果这些项目首先不在字典中。你的代码结构意味着你只有在TryAdd 成功时才会调用TryRemove。没有竞争条件。
猜你喜欢
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 2018-02-25
  • 2011-05-17
  • 2019-06-28
相关资源
最近更新 更多