【问题标题】:Is TryGetValue thread safe with itselfTryGetValue 线程本身是否安全
【发布时间】:2013-06-04 23:41:08
【问题描述】:

所以,我有一个Dictionary<KType,VType> Foo

在一个线程中我有:

void Thread1() {
  ...
  if (!Foo.TryGetValue(key, out v)) {
    Foo.Add(new VType());
  }
  ...
}

Foo 唯一一次被另一个线程访问是 TryGetValue

那么,我需要锁定多少钱?我可以这样做吗:

void Thread1() {
  ...
  if (!Foo.TryGetValue(key, out v)) {
    lock (syncobj) {
      Foo.Add(new VType());
    }
  }
  ...
}
void Thread2() {
  ...
  lock (syncobj) {
    Foo.TryGetValue(key, out v))
  }
  ...
}

Thread1 占程序计算的 90%,TryGetValue 被多次调用。因此,最好不要每次都调用 lock。

【问题讨论】:

标签: c# dictionary thread-safety trygetvalue


【解决方案1】:

如果在执行TryGetValue 的同时有可能在另一个线程上发生更新任何机会,则每次都必须lock

TryGetValue 对于自身来说是线程安全的,因为多个线程调用TryGetValue 不会相互干扰。但是,如果任何线程调用Add 而其他人正在对字典进行任何操作,那么就有损坏的可能性。

也就是说,锁可能并不可怕。你说TryGetValue被称为“很多次”,但你没有说多久一次。更重要的是,你没有说你可能多久发生一次冲突。在现代硬件上,一个无竞争的锁会花费你大约 50 纳秒的时间,所以这不是一个巨大的费用。您可能会尝试锁定只是为了看看它是如何执行的。你也可以考虑ReaderWriterLockSlim

了解ConcurrentDictionary 不是无锁数据结构很重要,尽管读取操作是以无锁方式完成的。它可能在您的情况下表现更好(可能会),但这不是给定的。

【讨论】:

  • 很高兴知道,这是出于好奇而不是必要的问题。我有点试图用速度的“原因”来证明这个问题的合理性。 ConcurrentDictionary 似乎是“正确”的做法。 (至少它是 IMO 更优雅的方式)。
  • 事实上,DictionaryReaderWriterLockSlim 的示例用例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 2012-08-21
  • 2023-03-12
  • 2019-11-21
  • 2013-12-30
  • 1970-01-01
相关资源
最近更新 更多