473,383 Members | 1,748 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Multi-threaded safe singleton class question

Hi,

I like the C# implemention of singleton class presented at MSDN. My question
is that is it correct or right thing to do to modify that class to make the
class will return the same instance if for the same parameter when calling
GetInstance?

public static Singleton GetInstance(string parameter)
{
//using a hashtable or some other type to hold the instance - parameter
will be the key
//if the key exists and the instance is not null then return the
instance, otherwise create new instance and then add to hashtable
}

Thanks a lot!
John
Nov 16 '05 #1
11 1872
We're doing exactly this for many of our "singleton" classes, and it
works just fine. Whether it's thread-safe is another question entirely.
I'll leave that to Jon Skeet or someone else more familiar with
threading.

Nov 16 '05 #2
John,

In this case, it isn't really a singleton, in the sense that you have
more than one Singleton instance.

In order to guarantee thread safety, you should pass the hashtable to
the static Synchronized method on the Hashtable class. This will pass a
wrapper to you which will provide thread safety when performing operations
(read and write) on the Hashtable.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"John Lee" <jo***@newsgroup.nospam> wrote in message
news:Or**************@TK2MSFTNGP09.phx.gbl...
Hi,

I like the C# implemention of singleton class presented at MSDN. My
question is that is it correct or right thing to do to modify that class
to make the class will return the same instance if for the same parameter
when calling GetInstance?

public static Singleton GetInstance(string parameter)
{
//using a hashtable or some other type to hold the instance - parameter
will be the key
//if the key exists and the instance is not null then return the
instance, otherwise create new instance and then add to hashtable
}

Thanks a lot!
John

Nov 16 '05 #3
John Lee <jo***@newsgroup.nospam> wrote:
I like the C# implemention of singleton class presented at MSDN. My question
is that is it correct or right thing to do to modify that class to make the
class will return the same instance if for the same parameter when calling
GetInstance?

public static Singleton GetInstance(string parameter)
{
//using a hashtable or some other type to hold the instance - parameter
will be the key
//if the key exists and the instance is not null then return the
instance, otherwise create new instance and then add to hashtable
}


As Nicholas said, that's not really a singleton - it's a factory
pattern implementation.

For thread safety, you should take out a lock:

static object mapLock = new object();

public static Singleton GetInstance (string parameter)
{
lock (mapLock)
{
// Check for existence, create new instance etc and return it
}
}

Don't try double-checked locking - unless you're *really, really*
confident that you're doing it right, and have got an expert to
validate it, preferrably by talking with even more experts, you may
well have a problem.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #4
Thanks very much!!!

Is this a thread-safe implementation?

=============================================
private static Hashtable htAzApps;

public static AzManStore GetInstance(string applicationName)
{
lock (htAzApps.SyncRoot)
{
if (htAzApps == null)
{
htAzApps = new Hashtable();
instance = new AzManStore(applicationName);
}
else
{
if (htAzApps.ContainsKey(applicationName))
instance = (AzManStore)htAzApps[applicationName];
else
instance = new AzManStore(applicationName);
}
}
return instance;
}
=================================================
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
John Lee <jo***@newsgroup.nospam> wrote:
I like the C# implemention of singleton class presented at MSDN. My
question
is that is it correct or right thing to do to modify that class to make
the
class will return the same instance if for the same parameter when
calling
GetInstance?

public static Singleton GetInstance(string parameter)
{
//using a hashtable or some other type to hold the instance -
parameter
will be the key
//if the key exists and the instance is not null then return the
instance, otherwise create new instance and then add to hashtable
}


As Nicholas said, that's not really a singleton - it's a factory
pattern implementation.

For thread safety, you should take out a lock:

static object mapLock = new object();

public static Singleton GetInstance (string parameter)
{
lock (mapLock)
{
// Check for existence, create new instance etc and return it
}
}

Don't try double-checked locking - unless you're *really, really*
confident that you're doing it right, and have got an expert to
validate it, preferrably by talking with even more experts, you may
well have a problem.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #5
John,
lock (htAzApps.SyncRoot)
{
if (htAzApps == null)


This will clearly not work. You have to verify that htAzApps != null
before the lock, or you'll get a NullReferenceException accessing
htAzApps.SyncRoot.

You can do what Jon showed you and lock on a separate object.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 16 '05 #6
John Lee <jo***@newsgroup.nospam> wrote:
Thanks very much!!!

Is this a thread-safe implementation?

=============================================
private static Hashtable htAzApps;

public static AzManStore GetInstance(string applicationName)
{
lock (htAzApps.SyncRoot)
{
if (htAzApps == null)
{
htAzApps = new Hashtable();
instance = new AzManStore(applicationName);
}
else
{
if (htAzApps.ContainsKey(applicationName))
instance = (AzManStore)htAzApps[applicationName];
else
instance = new AzManStore(applicationName);
}
}
return instance;
}
=================================================


Not quite - look at what you're trying to lock on, and then think about
the first time through... I'd suggest having a static variable with an
object created just for locking.

(Note that you're also never saving the instance back into the hash
table, which I assume you want to be.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #7
I normally do not use the singleton pattern, in the GOF sense. But
instead a "canonical object", providing the same feature: a single place
in the code where you can obtain your singleton.

The canonical object has the benefit of not requiring static's, and thus
you can easily replace the canonical object with (for example) an other
implementation that does debug-logging.

Example implementation:

class AzManRegistry {
public static AzManRegistry Global = new Applications();
IDictionary existing;
public AzManRegistry() { existing = new Hashtable(); }
public AzManStore Instance(string applicationName) {
// Registry is monotonic, so we can use any existing
// entry if there is one... without synchronization
if ( existing.ContainsKey(applicationName) )
return existing[applicationName];
lock (existing.SyncRoot) {
// we need to recheck existance inside the critical region
if ( !existing.ContainsKey(applicationName) )
existing[applicationName] = new AzManStore(applicationName);
return (AzManStore)existing[applicationName];
}
}
}

some other place:

AzManRegistry.Global.Instance("foo");

--
Helge
Nov 16 '05 #8
Yes, you are right!

Does the following code work?

private static Hashtable htAzApps = new Hashtable();
public static AzManStore GetInstance(string applicationName)
{
lock (htAzApps.SyncRoot)
{
if (htAzApps.ContainsKey(applicationName))
instance = (AzManStore)htAzApps[applicationName];
else
{
instance = new AzManStore(applicationName);
htAzApps.Add(applicationName, instance);
}
}
return instance;
}

Thanks very much!
John

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:ep****************@TK2MSFTNGP14.phx.gbl...
John,
lock (htAzApps.SyncRoot)
{
if (htAzApps == null)


This will clearly not work. You have to verify that htAzApps != null
before the lock, or you'll get a NullReferenceException accessing
htAzApps.SyncRoot.

You can do what Jon showed you and lock on a separate object.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Nov 16 '05 #9
Helge Jensen <he**********@slog.dk> wrote:
I normally do not use the singleton pattern, in the GOF sense. But
instead a "canonical object", providing the same feature: a single place
in the code where you can obtain your singleton.

The canonical object has the benefit of not requiring static's, and thus
you can easily replace the canonical object with (for example) an other
implementation that does debug-logging.

Example implementation:

class AzManRegistry {
public static AzManRegistry Global = new Applications();
IDictionary existing;
public AzManRegistry() { existing = new Hashtable(); }
public AzManStore Instance(string applicationName) {
// Registry is monotonic, so we can use any existing
// entry if there is one... without synchronization
if ( existing.ContainsKey(applicationName) )
return existing[applicationName];
lock (existing.SyncRoot) {
// we need to recheck existance inside the critical region
if ( !existing.ContainsKey(applicationName) )
existing[applicationName] = new AzManStore(applicationName);
return (AzManStore)existing[applicationName];
}
}
}


You're still relying on double-checked locking, which doesn't work in
..NET without extra volatility. In the above, I don't believe there's
anything to stop the JIT from reordering things such that the new entry
in the hashtable becomes visible before all the writes in the
AzManStore constructor have finished executing.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #10
Jon Skeet [C# MVP] wrote:
Helge Jensen <he**********@slog.dk> wrote: You're still relying on double-checked locking, which doesn't work in
.NET without extra volatility. In the above, I don't believe there's
anything to stop the JIT from reordering things such that the new entry
in the hashtable becomes visible before all the writes in the
AzManStore constructor have finished executing.
BTW: the reason I posted the solution was to present the
"canonical-object" as opposed to the "singleton".

Secondly, I'm very interested in the actual problem in the code. The
code is almost identical to production-code I have written. So I am very
interested in knowing exactly what is wrong with it!

I'm not really _sure_ what's the problem. Is it the check outside the lock?
// Registry is monotonic, so we can use any existing
// entry if there is one... without synchronization
if ( existing.ContainsKey(applicationName) )
return existing[applicationName];
I can see the issue, if the impl. of "existing[object item] { set }",
changes the representation of "existing" in a way that makes a
concurrent "existing[object item] { get }" either: diverge, throw, or
(very inlikely) return true.

Is this the problem? I don't think it's a problem with
System.Collections.Hashtable though. (It's not a problem that would
occur in my own Hashtable implementation, due to care in the way the
underlying datastructure is updated :)

Or is it that the AzManStore constructor inside the lock can be moved
outside the lock and executed before the lock, effectively doing:

AzManStore _moved_outside_lock = new AzManStore(applicationName);
if ( existing.ContainsKey(applicationName) )
return existing[applicationName];
lock (existing.SyncRoot) {
// we need to recheck existance inside the critical region
if ( !existing.ContainsKey(applicationName) )
existing[applicationName] = _moved_outside_lock;
return (AzManStore)existing[applicationName];
}


Which would seem pretty odd to me...

Best guess (from your explanation as I read it, I may be wrong) is that
the AzManStore-construtor would not have been completely evaluated
before invoking "existing[applicationName] { set }" on the new object.
But in that case locking wouldn't help at all, at least from what I can
reason.

or is it something even more exotic?

I would really appreciate an exact description, or reference to an
article, which would make it possible for me to understand and avoid
this problem .

--
Helge
Nov 16 '05 #11
Helge Jensen <he**********@slog.dk> wrote:
You're still relying on double-checked locking, which doesn't work in
.NET without extra volatility. In the above, I don't believe there's
anything to stop the JIT from reordering things such that the new entry
in the hashtable becomes visible before all the writes in the
AzManStore constructor have finished executing.
BTW: the reason I posted the solution was to present the
"canonical-object" as opposed to the "singleton".


But if you're going to post sample code and suggest that people use it,
you should make sure it's thread-safe - certainly in a question about
thread safety!
Secondly, I'm very interested in the actual problem in the code. The
code is almost identical to production-code I have written. So I am very
interested in knowing exactly what is wrong with it!

I'm not really _sure_ what's the problem. Is it the check outside the
lock?


Yes. Read up on double-checked locking and why it's broken in Java and
..NET. A simple google search should be fine.
> // Registry is monotonic, so we can use any existing
> // entry if there is one... without synchronization
> if ( existing.ContainsKey(applicationName) )
> return existing[applicationName];


I can see the issue, if the impl. of "existing[object item] { set }",
changes the representation of "existing" in a way that makes a
concurrent "existing[object item] { get }" either: diverge, throw, or
(very inlikely) return true.

Is this the problem? I don't think it's a problem with
System.Collections.Hashtable though. (It's not a problem that would
occur in my own Hashtable implementation, due to care in the way the
underlying datastructure is updated :)

Or is it that the AzManStore constructor inside the lock can be moved
outside the lock and executed before the lock, effectively doing:


To put it very briefly (as my dinner is waiting) - writes within the
constructor may be made visible to a reading thread *after* the write
into the hashtable. That means another thread could start using the
object before it had really been properly initialised.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

37
by: ajikoe | last post by:
Hello, Is anyone has experiance in running python code to run multi thread parallel in multi processor. Is it possible ? Can python manage which cpu shoud do every thread? Sincerely Yours,...
4
by: Frank Jona | last post by:
Intellisense with C# and a multi-file assembly is not working. With VB.NET it is working. Is there a fix availible? We're using VisualStudio 2003 Regards Frank
12
by: * ProteanThread * | last post by:
but depends upon the clique: ...
0
by: frankenberry | last post by:
I have multi-page tiff files. I need to extract individual frames from the multi-page tiffs and save them as single-page tiffs. 95% of the time I receive multi-page tiffs containing 1 or more black...
6
by: cody | last post by:
What are multi file assemblies good for? What are the advantages of using multiple assemblies (A.DLL+B.DLL) vs. a single multi file assembly (A.DLL+A.NETMODULE)?
6
by: Joe | last post by:
I have 2 multi-list boxes, 1 displays course categories based on a table called CATEGORIES. This table has 2 fields CATEGORY_ID, CATEGORY_NAME The other multi-list box displays courses based on...
4
by: mimmo | last post by:
Hi! I should convert the accented letters of a string in the correspondent letters not accented. But when I compile with -Wall it give me: warning: multi-character character constant Do the...
5
by: Shane Story | last post by:
I can seem to get the dimensions of a frame in a multiframe tiff. After selecting activeframe, the Width/Height is still really much larger than the page's actual dimensions. When I split a...
0
by: Sabri.Pllana | last post by:
We apologize if you receive multiple copies of this call for papers. *********************************************************************** 2008 International Workshop on Multi-Core Computing...
1
by: mknoll217 | last post by:
I am recieving this error from my code: The multi-part identifier "PAR.UniqueID" could not be bound. The multi-part identifier "Salary.UniqueID" could not be bound. The multi-part identifier...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.