DEV Community

Cover image for Design Patterns: Singleton

Design Patterns: Singleton

Ryan on November 24, 2019

Hey guys, thanks for being here! I've decided to start writing some posts as I review design patterns. Design patterns help provide a general and r...
Collapse
 
paulsmithkc profile image
Paul Smith • Edited

Do not use a Singleton to solve concurrency problems. You will end up creating concurrency problems, where there weren't concurrency problems to begin with.

Without a Singleton typically every thread will have it's own object which will usually be just fine. However with a Singleton every thread in your application will end up with the same instance of said object(s) and that is gaurenteed, even for trivial cases, to cause concurrency problems.

Instead of implementing Singleton, use frameworks and libraries with proper support for concurrency, that do not force/encourage you to create Singletons.

Collapse
 
antomor profile image
Antonio Morrone • Edited

Hy Ryan,
Thank you for the clear explanation. If interested, you can find out a detailed description of the problems related to c# singleton implementations.

Collapse
 
vdedodev profile image
Vincent Dedo

Singletons are always overused, and when that happens people with opinions roll in telling you it's an anti-pattern. I've found that most of the time I don't actually need a singleton, it just makes life easier. I haven't seen a really bad usage of it yet, so I'd like to see one if those people are in a sharing mood.

Collapse
 
gochev profile image
Nayden Gochev

I find this wrong and buggy, if two thread invoke the Instance at the same time there is a chance two variables to be created and in fact two different instances to be received by the two threads.

I am not a C# guy, sorry but usually in Java volatile and the double check locking helps I believe you can do the same in C#. Also I know in C# you have a Lazy<> which should be used ... but this pattern implementation is not good :( :(

Maybe there is some additional static magic that C# do, but I find it a bit smelly :D

I think the correct implementation is

public sealed class Singleton 
{
    private static readonly Lazy<Singleton>lazy = new Lazy<Singleton>(()=>new Singleton());

    public static Singleton Instance
    { 
        get 
        { 
            return lazy.Value; 
        } 
    }

    private Singleton() 
    {
    }
}

P.S. sorry for the wrong formatting (if it is wrong) I use { on the same line... :D:D:D so :D maybe I messed something :D

Collapse
 
gochev profile image
Nayden Gochev • Edited

oh yes also en.wikipedia.org/wiki/Double-check...

here you can check the proper implementation of your example

public class MySingleton {
    private static object myLock = new object();
    private static volatile MySingleton mySingleton = null; // 'volatile' is unnecessary in .NET 2.0 and later

    private MySingleton() {
    }

    public static MySingleton GetInstance() {
        if (mySingleton == null) { // 1st check
            lock (myLock) {
                if (mySingleton == null) { // 2nd (double) check
                    mySingleton = new MySingleton();
                    // In .NET 1.1, write-release semantics are implicitly handled by marking mySingleton with
                    // 'volatile', which inserts the necessary memory barriers between the constructor call
                    // and the write to mySingleton. The barriers created by the lock are not sufficient
                    // because the object is made visible before the lock is released. In .NET 2.0 and later,
                    // the lock is sufficient and 'volatile' is not needed.
                }
            }
        }
        // In .NET 1.1, the barriers created by the lock are not sufficient because not all threads will
        // acquire the lock. A fence for read-acquire semantics is needed between the test of mySingleton
        // (above) and the use of its contents. This fence is automatically inserted because mySingleton is
        // marked as 'volatile'.
        // In .NET 2.0 and later, 'volatile' is not required.
        return mySingleton;
    }
}

without lazy, az you can see volatile is NOT required now days, but double checked locking is !

Collapse
 
muhammadhasham profile image
Muhammad Hasham

Great write-up! another use case for singleton pattern can be that of a database connection. It is encourage to have a single database connection opened that should be used by all resources. :-)

Collapse
 
josefsabl profile image
josefsabl

Please, don't use singleton for DB connections.

Collapse
 
fathonir profile image
Fathoni Rokhman

Why? Is there any problems if we implemented it?

Thread Thread
 
jonathanhiggs profile image
Jonathan Higgs

One thread calls conn.Close() just before the other tries to execute a query...

Collapse
 
jignex profile image
Jignesh Thummar

Very good explanation, Magento 1 used to use Singleton pattern widely specially for read only objects

Collapse
 
josefsabl profile image
josefsabl • Edited

There are not many situations where singleton is cool and I mostly consider it an antipattern. The only defensible use I found so far are the sort of meta-features like logging or profiling as you are not always able to inject these as services.

Collapse
 
rolandcsibrei profile image
Roland Csibrei • Edited

Beware, in some cases in a multithread application you could end up with more "singleton" instances if you don't use lock. You can lock the whole factory method or the singleton object.

Collapse
 
yoann_buzenet profile image
Yoann Buzenet

Thanks for the article!