Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You may well be creating multiple instances, but these will get garbage collected because they are not used anywhere. In no case does the static _instance field variable change its value more than once, the single time that it goes from null to a valid value. Hence consumers of this code will only ever see the same instance, despite the fact that multiple instances have been created. </p> <p><strong>Lock free programming</strong></p> <p><a href="http://www.bluebytesoftware.com/blog/Default.aspx">Joe Duffy</a>, in his book entitled <em>Concurrent Programming on Windows</em> actually analyses this very pattern that you are trying to use on chapter 10, Memory models and Lock Freedom, page 526. </p> <p>He refers to this pattern as a Lazy initialization of a relaxed reference: </p> <pre><code>public class LazyInitRelaxedRef&lt;T&gt; where T : class { private volatile T m_value; private Func&lt;T&gt; m_factory; public LazyInitRelaxedRef(Func&lt;T&gt; factory) { m_factory = factory; } public T Value { get { if (m_value == null) Interlocked.CompareExchange(ref m_value, m_factory(), null); return m_value; } } /// &lt;summary&gt; /// An alternative version of the above Value accessor that disposes /// of garbage if it loses the race to publish a new value. (Page 527.) /// &lt;/summary&gt; public T ValueWithDisposalOfGarbage { get { if (m_value == null) { T obj = m_factory(); if (Interlocked.CompareExchange(ref m_value, obj, null) != null &amp;&amp; obj is IDisposable) ((IDisposable)obj).Dispose(); } return m_value; } } } </code></pre> <p>As we can see, in the above sample methods are lock free at the price of creating throw-away objects. In any case the Value property will not change for consumers of such an API. </p> <p><strong>Balancing Trade-offs</strong></p> <p>Lock Freedom comes at a price and is a matter of choosing your trade-offs carefully. In this case the price of lock freedom is that you have to create instances of objects that you are not going to use. This may be an acceptable price to pay since you know that by being lock free, there is a lower risk of deadlocks and also thread contention. </p> <p>In this <em>particular</em> instance however, the semantics of a singleton are in essence to Create a <em>single</em> instance of an object, so I would much rather opt for <a href="http://msdn.microsoft.com/en-us/library/dd642331.aspx"><code>Lazy&lt;T&gt;</code></a> as @Centro has quoted in his answer. </p> <p>Nevertheless, it still begs the question, when <em>should</em> we use <code>Interlocked.CompareExchange</code>? I liked your example, it is quite thought provoking and many people are very quick to diss it as wrong when it is not <em>horribly</em> wrong as @Blindy quotes. </p> <p>It all boils down to whether you have calculated the tradeoffs and decided: </p> <ul> <li>How important is it that you produce one and only one instance? </li> <li>How important is it to be lock free? </li> </ul> <p>As long as you are aware of the trade-offs and make it a conscious decision to create new objects for the benefit of being lock free, then your example could also be an acceptable answer. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload