今天我在使用Lazy
<T>
时发现了一个有趣的情况(在我看来)。
http://msdn.microsoft.com/zh-cn/library/system.threading.lazythreadsafetymode.aspx
PublicationOnly:
When multiple threads try to initialize a Lazy instance simultaneously, all threads are allowed to run the initialization method ... Any instances of T that were created by the competing threads are discarded.
If we look at the code of Lazy
<T>
.LazyInitValue() we will find that there is no check for IDisposable implementation and resoruces may leak here:case LazyThreadSafetyMode.PublicationOnly: boxed = this.CreateValue(); if (Interlocked.CompareExchange(ref this.m_boxed, boxed, null) != null) { //* boxed.Dispose(); -> see below. boxed = (Boxed<T>) this.m_boxed; } break;
目前唯一确保只创建一个实例的方法是使用LazyThreadSafetyMode.ExceptionAndPublication
。
所以我有两个问题:
- Do I miss something or we can see that few insntance can be created and resources can leak in this situation ?
If it's correct assumption why not to check for IDisposable in this situation and implement Dispose() on Boxed
<T>
such that it delegates disposal to the Boxed instance ofT
if it implements IDisposable or in some different way:class Boxed<T> { internal T m_value; void Dispose() { if (m_value is IDisposable) { ((IDisposable) m_value).Dispose(); } } }