Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton in current thread

I have my singleton as below:

public class CurrentSingleton
{
    private static CurrentSingleton uniqueInstance = null;
    private static object syncRoot = new Object();
    private CurrentSingleton() { }

    public static CurrentSingleton getInstance()
    {
        if (uniqueInstance == null)
        {
            lock (syncRoot)
            {
                if (uniqueInstance == null)
                    uniqueInstance = new CurrentSingleton();
            }
        }
        return uniqueInstance;
    }
}

I would like check, if I will have two thread, are there two different singletons? I think, I shall have two different singletons (with different references), so what I'm doing:

class Program
{
    static void Main(string[] args)
    {
        int currentCounter = 0;
        for (int i = 0; i < 100; i++)
        {
            cs1 = null;
            cs2 = null;

            Thread ct1 = new Thread(cfun1);
            Thread ct2 = new Thread(cfun2);
            ct1.Start();
            ct2.Start(); 
            if (cs1 == cs2) currentCounter++;
        }
        Console.WriteLine(currentCounter);
        Console.Read();

    }

    static CurrentSingleton cs1;
    static CurrentSingleton cs2;

    static void cfun1()
    {
        cs1 = CurrentSingleton.getInstance();
    }

    static void cfun2()
    {
        cs2 = CurrentSingleton.getInstance();
    }
}

I suppose that I should got currentCounter = 0 (in this case every two singleton are different - because are creating by other threrad). Unfortunately, I got for example currentCounter = 70 so in 70 cases I have the same singletons... Could you tell me why?

like image 440
makcis Avatar asked Dec 01 '22 16:12

makcis


1 Answers

I would like check, if I will have two thread, are there two different singletons

No, there are not. A static field is shared across each entire AppDomain, not each thread.

If you want to have separate values per thread, I'd recommend using ThreadLocal<T> to store the backing data, as this will provide a nice wrapper for per-thread data.

Also, in C#, it's typically better to implement a lazy singleton via Lazy<T> instead of via double checked locking. This would look like:

public sealed class CurrentSingleton // Seal your singletons if possible
{
    private static Lazy<CurrentSingleton> uniqueInstance = new Lazy<CurrentSingleton>(() => new CurrentSingleton());
    private CurrentSingleton() { }

    public static CurrentSingleton Instance  // use a property, since this is C#...
    {
        get { return uniqueInstance.Value; }
    }
}

To make a class that provides one instance per thread, you could use:

public sealed class InstancePerThread
{
    private static ThreadLocal<InstancePerThread> instances = new ThreadLocal<InstancePerThread>(() => new InstancePerThread());

    private InstancePerThread() {}
    public static InstancePerThread Instance
    {
        get { return instances.Value; }
    }
}
like image 181
Reed Copsey Avatar answered Dec 13 '22 00:12

Reed Copsey