Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConcurrentDictionary GetOrAdd value factory is not thread safe #24293

Closed
nrusitska opened this issue Nov 30, 2017 · 2 comments
Closed

ConcurrentDictionary GetOrAdd value factory is not thread safe #24293

nrusitska opened this issue Nov 30, 2017 · 2 comments
Milestone

Comments

@nrusitska
Copy link

When using GetOrAdd with a Value Factory, the execution of the factory is not thread safe and may be called multiple times.

Being called from multiple threads, this method first tries to find a present value (threadsafe),
then executes the value factory (unsafe) and finally inserts the value (safe again).
If the execution of the value factory takes longer, it's quite likely that is will be called each time.
just by the following TryAddInternal all the duplicate values are dismissed.

https://github.com/dotnet/corefx/blob/655af2fab48c1d0fdae352786d8371d0d13a81a7/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs#L987-L990

I suppose, a lock must be acquired before executing the value function.
(BTW this problem also applies to GetOrAdd with the value parameter, but is way less likely to happen in a real scenario)

Best regards!
Niko

@stephentoub
Copy link
Member

It is thread-safe, and yes, the value factory may be called multiple times. It's required that the delegate provided be able to be invoked concurrently with itself; if that's not the case, that's a bug in the usage rather than in the implementation of the dictionary. We explicitly do not want to take a lock here.

@benaadams
Copy link
Member

The Value Factory is provided by the caller. Whether or not that is thread-safe (or needs to be) is up to the caller and controlled by them.

alexmg referenced this issue in autofac/Autofac Jan 13, 2019
Use lock only if instance not created yet

ConcurrentDictionary GetOrAdd AddOrUpdate with value factory is not thread safe, so lock still needed
https://github.com/dotnet/corefx/issues/25609
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.1.0 milestone Jan 31, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants