I understand. Perhaps I am looking for a different design pattern then. If
my requirements are to only allow 1 instance at a time and prevent other
threads from changing that instance while it is in use, what would I use?
Essentially, I would be putting all the requests/threads in a line and only
allow 1 thread to instantiate and do its work while the others wait in line
for it to become available.
Thanks for your help
> Locking only prevents simultaneous access to a variable by two threads.
>
[quoted text clipped - 69 lines]
> > // Wait for user
> > Console.Read();
You would have to place a lock on the object itself before accessing it from
different threads:
Like this:
Singleton mySingleton = Singleton.Instance();
lock (mySingleton)
{
s1.Count = 2;
// as long as you stay inside the
// locked section, s1.Count is
// guaranteed to stay the same
}
-Philippe
> I understand. Perhaps I am looking for a different design pattern then. If
> my requirements are to only allow 1 instance at a time and prevent other
[quoted text clipped - 78 lines]
> > > // Wait for user
> > > Console.Read();
Chris Fink - 12 Mar 2008 23:19 GMT
Thank You.
I guess this means there is no way to make the singleton thread safe, but
instead you need to make the singleton instance thread safe. This will work
as long as all future consumers of this class are clear it is not a thread
safe class.
> You would have to place a lock on the object itself before accessing it from
> different threads:
[quoted text clipped - 95 lines]
> > > > // Wait for user
> > > > Console.Read();
Family Tree Mike - 12 Mar 2008 23:28 GMT
Jon Skeet had a recent post about making a "thread singleton" object through
an attribute (I think). I cannot find the post again, and cannot remember
the keyword. I'm sure he will recall and post. Perhaps this is the solution
for you.
> I understand. Perhaps I am looking for a different design pattern then.
Just judging from the sample code you posted, I think so. If anything,
I'd say that the singleton pattern is the opposite of what you want.
> If my requirements are to only allow 1 instance at a time and prevent
> other
> threads from changing that instance while it is in use, what would I use?
Your example doesn't show multiple threads trying to change the object at
the same time. Instead, it performs all of the changes in a single thread.
As far as what your example does show, there's not really anything you can
do to prevent that. You seem to want there to only be a single variable
referencing an instance of a class, but no matter what you do, you could
always just assign the reference found in one variable to another
variable. There's no way to detect that scenario from within the class,
nor do I think it makes any sense at all to try to prevent it.
Now, let's assume you had instead posted an example where the same object
is in fact used from multiple threads. It _is_ possible to make a class
thread safe, but without knowing more about what exactly you're trying to
do, it's hard to advise you.
One of my favorite ways to deal with thread safety is to make a class
immutable. But this only applies in certain situations. Another way is
to make sure that any method that can mutate the class is protected
internally with a lock() statement. This can be a good solution, but it
may involve writing a lot of lock() statements and can incur some
performance penalty, especially when there is actually some contention for
the object.
> Essentially, I would be putting all the requests/threads in a line and
> only
> allow 1 thread to instantiate and do its work while the others wait in
> line
> for it to become available.
This approach is antithetical to the whole point of multithreading. Why
would you want to have multiple threads that intentionally serialize
themselves on the same object? You might as well just have a single
thread use the same object for multiple iterations of the task.
Again, a better-elaborated explanation of what you're really trying to do
would go a long way.
Pete
Martin Bonner - 13 Mar 2008 11:59 GMT
On Mar 12, 11:42 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> It _is_ possible to make a class
> thread safe, but without knowing more about what exactly you're trying to
> do, it's hard to advise you.
>
> One of my favorite ways to deal with thread safety is to make a class
> immutable. But this only applies in certain situations.
... but when it does apply it's the way to go!
> Another way is
> to make sure that any method that can mutate the class is protected
> internally with a lock() statement. This can be a good solution, but it
> may involve writing a lot of lock() statements and can incur some
> performance penalty, especially when there is actually some contention for
> the object.
Can I inject a word of caution here? It is not sufficient to have a
lock on all the mutating functions - you need to make sure that all
the mutations you need to make are provided by member functions which
take a lock.
For example, if you have a simple integer property whose setter
function locks, it is /not/ possible to reliably increment the
property. The compiler will turn:
var.Property++;
into (in pseudo code)
int temp = var.get__Property();
temp++;
var.set__Property(temp);
The call to set_Property will grab the lock all right, but that is too
late. We really needed to grab the lock /before/ the call to the
getter!
(I am pretty sure that Peter knows this already, but others may not
and just slapping locks on the mutators is a superficially attractive
solution.)
> Again, a better-elaborated explanation of what you're really trying to do
> would go a long way.
Seconded!
Jon Skeet [C# MVP] - 13 Mar 2008 12:08 GMT
> Can I inject a word of caution here? It is not sufficient to have a
> lock on all the mutating functions - you need to make sure that all
[quoted text clipped - 13 lines]
> late. We really needed to grab the lock /before/ the call to the
> getter!
Not only that - we need to *keep* the lock while we increment. Adding a
lock to the getter isn't good enough, as two threads could both get
(acquiring and releasing the lock), then both increment, then both set
(acquiring and releasing the lock). You'd only "see" one increment as a
result.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Martin Bonner - 13 Mar 2008 16:31 GMT
> > Can I inject a word of caution here? It is not sufficient to have a
> > lock on all the mutating functions - you need to make sure that all
[quoted text clipped - 19 lines]
> (acquiring and releasing the lock). You'd only "see" one increment as a
> result.
Yes, that was exactly what I meant (grab the lock before we get the
value, and keep hold of it until after we have finished setting).
Thanks for clarifying.
Peter Duniho - 13 Mar 2008 18:22 GMT
> Can I inject a word of caution here? It is not sufficient to have a
> lock on all the mutating functions - you need to make sure that all
> the mutations you need to make are provided by member functions which
> take a lock. [...]
Yes, sorry...my post was vaguely written. Thanks for the clarification.
Pete