سؤال

So, I've got a Dictionary<KType,VType> Foo

In one thread I have:

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

The only time Foo is ever accessed by another thread is by a TryGetValue.

So, how much to I need to lock? Can I do something like:

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

The Thread1 is 90% of the program computation and TryGetValue is called many times. So, preferably, I would like to not have to call lock every time.

هل كانت مفيدة؟

المحلول

You have to lock every time if there's any chance that an update can occur on another thread at the same time a TryGetValue is being executed.

TryGetValue is thread-safe with itself, in that multiple threads calling TryGetValue won't interfere with each other. But if any thread calls Add while others are doing anything else with the dictionary, then there's the possibility of corruption.

That said, a lock might not be terrible. You say that TryGetValue is called "many times", but you don't say how often. More importantly, you don't say how often you're likely to get a conflict. An uncontended lock is going to cost you something like 50 nanoseconds on modern hardware, so it's not a huge expense. You might try the lock just to see how it performs. You might also consider a ReaderWriterLockSlim.

It's important to understand that ConcurrentDictionary is not a lock-free data structure, although read operations are done in a lock-free manner. It might perform better in your situation (probably will), but that's not a given.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top