1

If a singleton which is accessed from multiple threads is used, and the singleton itself is threadsafe, which thread will block when the singleton is accessed?

For example thinking that there is a mainthread A . A first accessed the singleton S. Then does something else.

A bit later thread B accesses the singleton S.

If B accesses S, will the singleton still be in context of thread A and also block thread A or only thread B (and other ones trying to actually access it?)

-> accesses
A->S {}
A->X {}
B->S {
...
C-S 
} - will B only block C or also A?

To answer to the questions: thread safe singleton (stripped down):

private static volatile Singleton instance;
    private static object _sync = new Object();

    private Singleton() {
        // dosomething...
    }

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (_sync)
                {
                    if (instance == null)
                        instance = new Singleton();
                }
            }

            return instance;
        }
    }

(and of cause locking in methods)

And the question is mostly specific to the following point: I know that the lock will prevent multiple threads to access the same region of code. My question is specific to the following point:

If the original thread in which scope the Singleton was produced does not hold the lock, will it also be blocked if another thread accesses the lock, as the Singleton Instance was created in the scope? Will the singleton just only run in the scope of the original thread?

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
Offler
  • 1,223
  • 1
  • 12
  • 34
  • 2
    What do you mean by a threadsafe singleton? Can you post some code? – Mark Byers Dec 18 '12 at 13:37
  • It's just an instance - there's nothing special about it other than that you are preventing certain things from happening. It will run in the context in which it's called. – zimdanen Dec 18 '12 at 13:44

3 Answers3

0

Usually, thread safety for a singleton means mutual exclusion. That is, if a thread needs to use the singleton, it must acquire a lock/token, do what it needs, and release the token. During the whole time it is holding the token, no other thread will be able to acquire it. Any thread that tries that will be blocked and placed in a FIFO queue and will receive the token as soon as the holder releases it. This ensures only one thread accesses the protected resource (a singleton object in this case) at a time.

This is the typical scenario; your mileage might vary.

On a related note, Singleton is considered a bad idea by most people.

Syncronization mechanisms for C# are covered in part 2 of the tutorial linked by makc, which is quite nice.

Community
  • 1
  • 1
dario_ramos
  • 7,118
  • 9
  • 61
  • 108
  • 1
    I know that some (not the most, but the loudest) nowadays consider SingleTons as evil. But hey, some loud people also consider oo as evil for testing, and want to switch to functional programming. – Offler Dec 18 '12 at 14:20
0

Thread safe normally means only one thread can access it at a time. Locks around critical sections will mean multiple threads trying to run that piece of code will be blocked and only one at a time can proceed and access it.

Let's assume in your question that the class is synchronised at the class level, then while A is calling methods on S any other thread trying to call S at the same time will have to wait until A is finished.

Once A has finished running S then all waiting threads can be re-scheduled and one of them will then acquire the lock and run S (blocking any remaining waiting threads).

Meanwhile...A can go ahead and run X while someone else is accessing S (unless they share the same lock).

Think of a lock - specifically a mutex in this example - as a token, only the thread holding the token can run the code it protects. once it's done it drops the token and the next thread that picks it up can proceed.

Typically your synchronisation is done at a finer-grained level than across the whole class, say on a specific method or a specific block of code within a method. This avoids threads wasting time waiting around when they could actually both access different methods that don't affect each other.

Paolo
  • 22,188
  • 6
  • 42
  • 49
  • yep, i know that the lock will prevent multiple threads to access the same region of code. My question was specific to the point: I the original thread in which scope the Singleton was produced does not hold the lock, will it also be blocked, as the Singleton Instance was created in the scope? – Offler Dec 18 '12 at 14:22
  • As soon as A exits the block of code that instantiates the singleton the lock is released and other threads can access it. The context it's created in does not matter. The lock only prevents two threads creating an instance simultaneously, thereby ensuring only one instance is ever created. – Paolo Dec 18 '12 at 20:51
  • In general that would be the same as my original opinion. My problem is that I see a program where the singleton is created in program.cs. The main form which does not access the singleton blocks, if other threads (started by program) access the singleton. So far I haven't found a part which is used by signleton and main form. – Offler Dec 19 '12 at 07:03
  • If the main form is not accessing the singleton then your problem must lie elsewhere. Have you attached the debugger and looked at what locks the main form is waiting on? – Paolo Dec 19 '12 at 08:09
  • if i start using the debugger and press pause i always end up in the singleton... – Offler Dec 19 '12 at 10:09
  • That doesn't mean a lot. Have you opened the thread window and ensured you are looking at the main form thread? Now open the stack trace window and see what it's calling and what it is blocked on. – Paolo Dec 19 '12 at 11:03
  • On the Debug menu, point to Windows, and then click Threads. http://msdn.microsoft.com/en-us/library/w15yf86f%28v=vs.100%29.aspx – Paolo Dec 19 '12 at 15:22
0

It'll depend on how thread-safe is your singleton or any other object.

For example, if you use a Monitor or Mutex, only one thread will have access to the protected code block by one of these threading synchronization approaches. Let's say one thread tries to enter a synchronized code block and some other thread acquired the lock: then the second thread will wait till the first releases the lock.

In the other hand, if you use a Semaphore, you'll define how many threads can pass through a protected code block. Let's say the Semaphore allows 8 threads at the same time. If a possible 9th thread tries to enter to the protected code block it'll wait until Semaphore notifies that there's one or more slots available for the queued threads.

There're different strategies when it comes to synchronize objects when using multi-threading.

Check this MSDN article:

UPDATE

I've checked your code in your updated question body.

Definitively: yes. Any thread, even the main thread, will be blocked until the one that acquired the lock releases it

Imagine that this wouldn't be this way: some threading rules work for any thread excluding the main one. It would be a chance to have a non-synchronized code region.

lock statement compiles into something like a Monitor.Enter and Monitor.Exit. This means that the locked object acquires an exclusive lock for the current thread.

UPDATE 2

Taken from some OP comment:

Can you explain why? I mean if the main thread does nothing with the singleton in the moment, then the thread does not try to get that lock?

Ooops! I feel you forgot something about how threading works!

When you protect a code region using a thread synchronization approach like Monitor (lock keyword uses a Monitor behind the scene), you're blocking any thread that tries to enter to the protected/synchronized object rather than blocking any working thread until the Monitor releases the lock.

Let's say there're two threads A and B and you've this code:

lock(_syncObject)
{
    // Do some stuff
}

Thread A goes through the synchronized code region and B is a background worker that's doing some other stuff that won't go through the protected region. In this case, B won't be blocked.

In other words: when you synchronize threaded access to some region you're protecting an object. lock (or Mutex, AutoResetEvent or whatever) is not equivalent to something like an hypothetical Thread.SleepAll(). If any thread is started and working and no one goes through a synchronized object access, no thread will be blocked.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • yep, i know that the lock will prevent multiple threads to access the same region of code. My question was specific to the point: If the original thread in which scope the Singleton was produced does not hold the lock, will it also be blocked, as the Singleton Instance was created in the scope? – Offler Dec 18 '12 at 14:23
  • @Offer Does the thread which creates the singleton synchronizes the single instantiation? I mean, are you usking `lock`, `Monitor`, `Mutex`or something like that? – Matías Fidemraizer Dec 18 '12 at 14:36
  • @Offer then it depends on what you want to achieve. If thread synchronization is used to ensure that only one thread will be able to create the single instance of the singleton, this will work as expected. If such singleton exposes properties or so, the responsible of synchronizing the access to them is the caller. Are you following me? – Matías Fidemraizer Dec 18 '12 at 16:20
  • In general that would be the same as my original opinion. My problem is that I see a program where the singleton is created in program.cs. The main form which does not access the singleton blocks, if other threads (started by program) access the singleton. So far I haven't found a part which is used by signleton and main form. So if (A) does no longer hold the singleton, why should it be blocked? – Offler Dec 19 '12 at 07:04
  • CAn you explain why? I mean if the main thread does nothing with the singleton in the moment, then the thread does not try to get tha lock? – Offler Dec 19 '12 at 12:42