Reputation: 1003
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.
Upvotes: 2
Views: 3502
Reputation: 133950
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.
Upvotes: 7