Skip to content

Commit

Permalink
Fix for #635 SingleInstance lock
Browse files Browse the repository at this point in the history
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
  • Loading branch information
avtc authored and alexmg committed Jan 13, 2019
1 parent 2951f95 commit 9b0af51
Showing 1 changed file with 15 additions and 11 deletions.
26 changes: 15 additions & 11 deletions src/Autofac/Core/Lifetime/LifetimeScope.cs
Expand Up @@ -24,6 +24,7 @@
// OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
Expand All @@ -47,7 +48,7 @@ public class LifetimeScope : Disposable, ISharingLifetimeScope, IServiceProvider
/// Protects shared instances from concurrent access. Other members and the base class are threadsafe.
/// </summary>
private readonly object _synchRoot = new object();
private readonly IDictionary<Guid, object> _sharedInstances = new Dictionary<Guid, object>();
private readonly ConcurrentDictionary<Guid, object> _sharedInstances = new ConcurrentDictionary<Guid, object>();

private readonly ISharingLifetimeScope _parent;

Expand Down Expand Up @@ -302,20 +303,23 @@ public object GetOrCreateAndShare(Guid id, Func<object> creator)
{
if (creator == null) throw new ArgumentNullException(nameof(creator));

lock (_synchRoot)
object result;
if (!_sharedInstances.TryGetValue(id, out result))
{
object result;
if (!_sharedInstances.TryGetValue(id, out result))
lock (_synchRoot)
{
result = creator();
if (_sharedInstances.ContainsKey(id))
throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, LifetimeScopeResources.SelfConstructingDependencyDetected, result.GetType().FullName));

_sharedInstances.Add(id, result);
if (!_sharedInstances.TryGetValue(id, out result))
{
result = creator();
if (_sharedInstances.ContainsKey(id))
throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, LifetimeScopeResources.SelfConstructingDependencyDetected, result.GetType().FullName));

_sharedInstances.TryAdd(id, result);
}
}

return result;
}

return result;
}

/// <summary>
Expand Down

0 comments on commit 9b0af51

Please sign in to comment.