Re: C# Interview questions
- From: "Bruce Wood" <brucewood@xxxxxxxxxx>
- Date: 27 Apr 2006 17:04:04 -0700
William Stacey [MVP] wrote:
Here is another Jim-Dandy that works. Notice after the instance is created,
the only overhead is a simple "if" test on future gets.
using System;
using System.Threading;
public sealed class Singleton
{
private static Singleton instance;
private Singleton() // Don't allow public constructor.
{
}
public static Singleton Instance
{
get
{
// Note simple and fast double-checked locking that actually
works. Also note instance does not
// need to be volatile. The Interlocked class does not wait, nor
does it transition to kernel mode and is only
// called if instance is null. If two or more thread happen to
get into the "if" before instance is set,
// then the CompareExchange statement takes care of that case as
well.
if (instance == null)
Interlocked.CompareExchange(ref instance, new Singleton(),
null);
return instance;
}
}
}
Forgive my ignorance, but doesn't this just amount to double-check
locking? I'm no multithreading whiz, so I may be wrong, but I see
several problems with this code.
1) Testing for instance == null may suffer from caching problems: one
thread may have a cached value of "instance" that is still null, even
though it has been set on another thread. Given the next line, that
might not be a problem, but....
2) If the "if (instance == null)" line fails because of a caching
problem, or a race condition (instance was null when the test was done
but by the time we get to the CompareExchange call it is no longer
null), then "new Singleton()" will be called _before_ CompareExchange
is called, since the rule for method arguments is that they're
evaluated and their _values_ are passed to the method. So, you could
instantiate a second Singleton() and then, inside CompareExchange,
decide not to use it because some other thread has already set
"instance". Depending upon what the Singleton() constructor does, and
the consequences for having two Singleton instances around, this could
be bad... or not.
3) Even though CompareExchange guarantees that "instance" will tested
and set in one atomic operation, and I assume that it takes pains to
form a memory barrier so that other threads see the change as atomic,
I'm not sure that it guarantees that the _state of the Singleton
instance_ that was created preparing for the call will be correctly
updated into any memory cached by other threads. Are you sure that
CompareExchange creates a memory barrier in such a way that other
threads will not only see the correct "instance" reference, but will
also see the correct contents in all of the "instance"'s private fields?
.
- Follow-Ups:
- Re: C# Interview questions
- From: William Stacey [MVP]
- Re: C# Interview questions
- References:
- C# Interview questions
- From: Shark
- Re: C# Interview questions
- From: Mythran
- Re: C# Interview questions
- From: sloan
- Re: C# Interview questions
- From: Bruce Wood
- Re: C# Interview questions
- From: William Stacey [MVP]
- C# Interview questions
- Prev by Date: Detection of nullable types...
- Next by Date: Re: Open and Decrypt Private Key
- Previous by thread: Re: C# Interview questions
- Next by thread: Re: C# Interview questions
- Index(es):
Relevant Pages
|