2

Since I create the readonly static instance as soon as someone uses the class, no lazy loading, this code is thread safe and I do not need to follow the Double-checked locking design pattern, correct?

public class BusSingleton<T> where T : IEmpireEndpointConfig, new() { private static readonly BusSingleton<T> instance = new BusSingleton<T>(); private IBus bus; public IBus Bus { get { return this.bus; } } public static BusSingleton<T> Instance { get { return instance; } } private BusSingleton() { T config = new T(); bus = NServiceBus.Bus.Create(config.CreateConfiguration()); ((IStartableBus) bus).Start(); } } 
2
  • Possible duplicate of Thread Safe C# Singleton Pattern Commented Jan 18, 2017 at 20:56
  • I do not agree the duplicate suggestions. The duplicate just shows how to do double checked locking. This is asking "is double checked locking needed in this specific situation?" Commented Jan 18, 2017 at 20:58

2 Answers 2

2

During the static initializer the run-time puts a lock around the object's type so two instances of the initializer can not be run at the same time.

The only thing you must be careful of is if NServiceBus.Bus.Create, config.CreateConfiguration, or bus.Start() use multiple threads internally and try to access your object's type anywhere within the class/function on that other thread you could deadlock yourself if one of those three function calls does not return until after that internal thread is done.

When you do the traditional "lazy singleton" with double checked locking the static initializer will have already finished and you don't run the risk of deadlocking yourself.

So if you are confidant that those 3 functions will not try to access your type on another thread then it is fine to not use double checked locking for your use case.

Sign up to request clarification or add additional context in comments.

4 Comments

Does the static initializer lock work for all values of T, or just each? That is, if thread A does BusSingleton<Foo> and thread B does BusSingleton<Bar> - can the type initializer for BusSingleton run in parallel for each type of T, Bar and Foo? If that's how it works, then the instance constructors will run parallel, and thus Create and Start need to be thread safe, too.
Yes they can be run in parallel, when working with statics and generics just in your mind replace < and > with _. Now ask your question again "if thread at does BusSingleton_Foo_ and another thread does BusSingleton_Bar_ - can the type initializers run in parallel for Bar and Foo?" The answer to that is "Of course they can, they are two different types"
@vcsjones I do agree that Create must be thread safe, but assuming Create creates a new instance of the IStartableBus object then Start does not need to be thread safe because it is local to the function.
agree - but I don't know what NServiceBus does. For all I know Start accesses / uses some shared static in it's implementation (hypothetically). So the safety of this depends entirely on NServiceBus's API.
0

That looks safe as long as you don't need to delay the instantiation to run initalization code or anything like that. Which it sounds like you don't need. https://msdn.microsoft.com/en-us/library/ff650316.aspx

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.