diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs
index 6888486a..4190ed0c 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs
@@ -142,6 +142,12 @@ namespace Spring.Objects.Factory.Support
///
private readonly Hashtable factoryObjectProductCache = new Hashtable();
+
+ ///
+ /// Collection of singleton-specific locks to support locking singleton-specific critical sections
+ ///
+ private IDictionary singletonLocks = new Hashtable();
+
#region Constructor (s) / Destructor
///
@@ -1438,16 +1444,28 @@ namespace Spring.Objects.Factory.Support
///
protected virtual void DestroySingleton(string name)
{
+ object tempObject;
+
lock (singletonCache)
{
- object tempObject = singletonCache[name];
- singletonCache.Remove(name);
- registeredSingletons.Remove(name);
-
- object singletonInstance = tempObject;
- if (singletonInstance != null)
+ tempObject = singletonCache[name];
+
+ if (tempObject!=null)
{
- DestroyObject(name, singletonInstance);
+ singletonCache.Remove(name);
+ registeredSingletons.Remove(name);
+ }
+
+ if (tempObject!=null)
+ {
+ lock(GetSingletonLockFor(name))
+ {
+ object singletonInstance = tempObject;
+ if (singletonInstance != null)
+ {
+ DestroyObject(name, singletonInstance);
+ }
+ }
}
}
}
@@ -2122,35 +2140,48 @@ namespace Spring.Objects.Factory.Support
RootObjectDefinition objectDefinition,
object[] arguments)
{
+ object sharedInstance;
+
lock (singletonCache)
{
- object sharedInstance = singletonCache[objectName];
+ sharedInstance = singletonCache[objectName];
+
if (sharedInstance == null)
{
- #region Instrumentation
- if (log.IsDebugEnabled)
+ lock (GetSingletonLockFor(objectName))
{
- log.Debug(string.Format("Creating shared instance of singleton object '{0}'", objectName));
- }
- #endregion
+ lock (singletonCache)
+ {
+ if (singletonCache.Contains(objectName))
+ {
+ return singletonCache[objectName];
+ }
+ }
+ #region Instrumentation
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(string.Format("Creating shared instance of singleton object '{0}'", objectName));
+ }
+ #endregion
- BeforeSingletonCreation(objectName);
- try
- {
- sharedInstance = InstantiateObject(objectName, objectDefinition, arguments, true, false);
- }
- finally
- {
- AfterSingletonCreation(objectName);
- }
- AddSingleton(objectName, sharedInstance);
+ BeforeSingletonCreation(objectName);
+ try
+ {
+ sharedInstance = InstantiateObject(objectName, objectDefinition, arguments, true, false);
+ }
+ finally
+ {
+ AfterSingletonCreation(objectName);
+ }
+ AddSingleton(objectName, sharedInstance);
- #region Instrumentation
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format("Cached shared instance of singleton object '{0}'", objectName));
+ #region Instrumentation
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(string.Format("Cached shared instance of singleton object '{0}'", objectName));
+ }
+ #endregion
}
- #endregion
}
return sharedInstance;
}
@@ -2485,5 +2516,23 @@ namespace Spring.Objects.Factory.Support
{
return IsAlias(objectName) || ContainsLocalObject(objectName);
}
+
+
+ ///
+ /// Gets the singleton lock for a given object name.
+ ///
+ /// Name of the object.
+ /// lock object
+ private object GetSingletonLockFor(string objectName)
+ {
+ lock (singletonCache)
+ {
+ if (!singletonLocks.Contains(objectName))
+ {
+ singletonLocks.Add(objectName, new object());
+ }
+ return singletonLocks[objectName];
+ }
+ }
}
}
\ No newline at end of file