Issue in C# singleton with multi threading: a variable not intialized - c#

This is a simplified version of production code and running in multi thread with singleton. Compared to traditional singleton the additional thing is that I initialized client in the lock section.
When I trying to get the client by: Client client = Singleton.Instance.GetClient();, there is chance that client can be null (but the chance is very small).
public class Client
{
public int Value { get; set; } = 10;
}
public class Singleton
{
private static Singleton instance = null;
private static readonly object padlock = new object();
private Client client = null;
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
// Here is the interesting part!
instance.InitClient();
}
}
}
return instance;
}
}
private void InitClient()
{
this.client = new Client();
}
public Client GetClient()
{
return this.client;
}
}
This is how I testing it:
static void Main(string[] args)
{
Console.WriteLine("Input thread count: ");
int threadCount = Int32.Parse(Console.ReadLine().Trim());
List<Task> tasks = new List<Task>(threadCount);
for (int i = 0; i < threadCount; ++i)
{
tasks.Add(Task.Factory.StartNew(() => DoStuff()));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("All threads complete");
}
private static void DoStuff()
{
Client client = Singleton.Instance.GetClient();
if (client.Value != 10)
{
Console.WriteLine($"Thread: {Thread.CurrentThread.ManagedThreadId}.");
}
}
And client can be null in occasionlly:
But when I moved the InitClient() into the private constructor of Singleton, I never meet the situation that client is null:
private Singleton()
{
this.InitClient();
}
I don't have any clue what is difference and what is wrong, thanks for the helping!

As soon as you call instance = new Singleton() inside the lock, "instance" is no longer null, meaning separate (threaded) calls to Singleton.Instance returns immediately, and a call to GetClient on that instance would be a race condition with the InitClient from the first call.
Initializing inside the constructor ensures "Instance" itself is initialized as soon as it's created. So subsequent calls from separate threads wouldn't race against anything.

Related

Are C# static methods synchronized and locked?

I have a static class that gets me a client..
public static ClientFactory {
private static Lazy<IClient> _MyClient;
public static IClient GetClient(ICache cache) {
if (_MyClient == null) {
_MyClient = new Lazy<IClient>(() => CreateClient(cache));
}
return _MyClient.Value;
}
private static IClient CreateClient(ICache cache) {
// code that takes 1-2 seconds to complete
return new Client(cache);
}
}
Is there any chance that I can have 2 or more clients created by writing code like this? Where the second client would overwrite the first one?
How should I update my code in a way, such that the constructor is called only once per application?
Thanks.
Yes, your code can result in multiple Client objects created. Use a static constructor to create the Lazy<IClient> instance:
public static ClientFactory
{
...
static ClientFactory()
{
_myClient = new Lazy<IClient>(() => CreateClient());
}
public IClient GetClient() => _myClient.Value;
}
Example execution from your code:
thread A evaluates _myClient == null as true, enters block
thread B evaluates _myClient == null as true, enters block
thread A creates Lazy<IClient> object and sets _myClient field
thread A exits if block
before thread B sets _myClient field with a new Lazy<IClient> object, thread A accesses _myCilent.Value property, resulting in the creation of your Client object
thread B sets the _myClient field to its new Lazy<IClient> object
thread B accesses the _myClient.Value property, creating a second Client object
all subsequent calls to GetClient will return this second instance of Client
Yes, there is a chance, consider this example, based on your input, a run of this simple program may result in initialization of one or two clients (run multiple times to see):
void Main()
{
System.Threading.Tasks.Parallel.Invoke(
() => ClientFactory.GetClient(1),
() => ClientFactory.GetClient(2));
}
// You can define other methods, fields, classes and namespaces here
public static class ClientFactory {
private static Lazy<IClient> _MyClient;
public static IClient GetClient(int init) {
Console.WriteLine(_MyClient == null);
if (_MyClient == null) {
Console.WriteLine(init);
_MyClient = new Lazy<IClient>(() => CreateClient());
}
return _MyClient.Value;
}
private static IClient CreateClient() {
// code that takes 1-2 seconds to complete
return new Client();
}
}
public interface IClient {
}
public class Client : IClient {
public Client() {
Console.WriteLine("Client constucrtor");
}
}
Two threads may be within the if (_MyClient == null) clause in the same time, creating multiple objects, only one assigned.

Why would the presence of a 'lock' statement in a C# method significantly increase its runtime, even if the lock statement is never executed?

For ten million iterations, I was comparing different ways of accessing a singleton.
Direct read of a static property is fastest.
Lazy<T>, whose Value property internally introduces s a null check, cast of boxed value, and access of boxed value takes a little longer (2x - 3x).
What I found startling is that a common double-check lock pattern, which is really just a null check for most accesses, was taking significantly longer (almost 5x in some cases) -- far longer than expected. I was also shocked to discover that simply commenting out the 'lock' statement, even if it was never hit, reduces the time closer to a basic direct access of static property, with a little extra overhead for the null check.
What is it about the mere presence of this 'lock' statement in the method, even if the lock statement is never executed, that's causing it to take so much more time? I assign the singleton(s) up-front in this test code, so the lock statement is never hit; yet, simply uncommenting the 'lock' line increases the runtime. I have no explanation.
Here's a short example you can paste in a console app and run to see the timings of a few different accesses.
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace SingletonInitializationMethodPerformanceTest
{
public class Program
{
private const int TestRuns = 5;
private const int AccessesPerTestRun = 10000000;
private static int _totalAccesses;
private static readonly Stopwatch Timer = new Stopwatch();
private static readonly Func<Singleton>[] Tests = { Singleton.LazyInstance, Singleton.InstanceWithLockPresent, Singleton.InstanceWithLockCommentedOut, Singleton.InstanceWithLockInSeparateMethod, Singleton.DirectlyReturnedInstance };
public static void Main(string[] args)
{
var results = Tests.Select(x => new int[TestRuns]).ToList();
Thread.CurrentThread.Priority = ThreadPriority.Highest; Thread.Sleep(3000);
for (var iRun = 0; iRun < TestRuns; iRun++)
for (var iTest = 0; iTest < Tests.Length; iTest++)
results[iTest][iRun] = RunTest(Tests[iTest]);
Console.Write($"Total accesses: {_totalAccesses}\n\n");
for (var iTest = 0; iTest < Tests.Length; iTest++)
Console.Write($"{Tests[iTest].Method.Name.PadRight(35, ' ')} [{string.Join(",", results[iTest].Select(x => x.ToString().PadLeft(5, ' ')))}]\n");
Console.ReadLine();
}
private static int RunTest(Func<Singleton> getSingleton)
{
Timer.Restart();
for (var i = 0; i < AccessesPerTestRun; i++)
_totalAccesses += getSingleton().Value;
Timer.Stop();
return (int)Timer.Elapsed.TotalMilliseconds;
}
}
public class Singleton
{
private static readonly object _initializationLock = new object();
private static Singleton _instance = new Singleton(); //Instance is pre-assigned for testing purposes, ensuring 'lock' statement is never hit; demonstrating the statement's presence alone increases runtime.
private static readonly Lazy<Singleton> _lazyInstance = new Lazy<Singleton>(() => new Singleton(), LazyThreadSafetyMode.ExecutionAndPublication);
public static Singleton LazyInstance() => _lazyInstance.Value;
public static Singleton InstanceWithLockPresent()
{
if (_instance == null)
{
lock (_initializationLock) //intentionally unreachable code; represents code that would be here if we were not pre-assigning the singleton for testing
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
public static Singleton InstanceWithLockCommentedOut()
{
if (_instance == null)
{
//lock (_initializationLock) //intentionally unreachable code; represents code that would be here if we were not pre-assigning the singleton for testing
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
public static Singleton InstanceWithLockInSeparateMethod() => _instance ?? DoLock();
private static Singleton DoLock()
{
lock (_initializationLock)
{
if (_instance == null)
{
_instance = new Singleton();
}
}
return _instance;
}
public static Singleton DirectlyReturnedInstance() => _instance;
public int Value => 1;
private Singleton()
{
}
}
}
Here are some example runtimes (total milliseconds per 10 million iterations, repeated five times for each method of accessing the singleton).
Most likely because a lock introduces a try/finally, a local, and quite a bit of code - plus memory barrier semantics, making the JIT not want to inline your method any more?
A common hack here is to have the success path in the main method, and the "double checked" failure path in a different method, so all that overhead only gets executed in the null case. For example:
return _doubleCheckInstance ?? SlowPath();
with a separate SlowPath method that does all the hard work including the lock and new

Need help tweaking c# multi-threaded routine

I've created a windows service which runs a multi-threaded routine on a machine with 24 cores, 48 virtual, using Parallel.ForEach. This service, which has been running great in a production environment, bulk copies data into an SQL Server database. Currently it does this very well, around 6000 inserts per second, but I believe it can be tweaked. Below is part of the code I am using; there's an example of current functionality and proposed changes for tweaking. As can be seen from the code, currently a lock is taken for every call to Add, which I believe makes the Parallel.ForEach somewhat non-parallel. So I'm looking for a "fix"; and hoping my new method, also defined in the code, would do the trick.
public class MainLoop
{
public void DoWork()
{
var options = new ParallelOptions
{
MaxDegreeOfParallelism = System.Environment.ProcessorCount * 2
};
var workQueueManager = new ObjWorkQueueManager(queueSize: 1000);
// ignore the fact that this while loop would be a never ending loop,
// there's other logic not shown here that exits the loop!
while (true)
{
ICollection<object> work = GetWork();
Parallel.ForEach(work, options, (item) =>
{
workQueueManager.AddOLD(item);
});
}
}
private ICollection<object> GetWork()
{
// return list of work from some arbitrary source
throw new NotImplementedException();
}
}
public class ObjWorkQueueManager
{
private readonly int _queueSize;
private ObjDataReader _queueDataHandler;
private readonly object _sync;
public ObjWorkQueueManager(int queueSize)
{
_queueSize = queueSize;
_queueDataHandler = new ObjDataReader(queueSize);
_sync = new object();
}
// current Add method works great, but blocks with EVERY call
public void AddOLD(object value)
{
lock (_sync)
{
if (_queueDataHandler.Add(value) == _queueSize)
{
// create a new thread to handle copying the queued data to repository
Thread t = new Thread(SaveQueuedData);
t.Start(_queueDataHandler);
// start a new queue
_queueDataHandler = new ObjDataReader(_queueSize);
}
}
}
// hoping for a new Add method to work better by blocking only
// every nth call where n = _queueSize
public void AddNEW(object value)
{
int queued;
if ((queued = _queueDataHandler.Add(value)) >= _queueSize)
{
lock (_sync)
{
if (queued == _queueSize)
{
Thread t = new Thread(SaveQueuedData);
t.Start(_queueDataHandler);
}
}
}
else if (queued == 0)
{
lock (_sync)
{
_queueDataHandler = new ObjDataReader(_queueSize);
AddNEW(value);
}
}
}
// this method will Bulk Copy data into an SQL DB
private void SaveQueuedData(object o)
{
// do something with o as ObjDataReader
}
}
// implements IDataReader, Read method of IDataReader dequeues from _innerQueue
public class ObjDataReader
{
private readonly int _capacity;
private Queue<object> _innerQueue;
public ObjDataReader(int capacity)
{
_capacity = capacity;
_innerQueue = new Queue<object>(capacity);
}
public int Add(object value)
{
if (_innerQueue.Count < _capacity)
{
_innerQueue.Enqueue(value);
return _innerQueue.Count;
}
return 0;
}
}

Singleton instance is always null

I have an ASP.net with MVC program with the current singleton class:
public sealed class Foo
{
private static volatile Foo_instance;
private static object syncRoot = new Object();
private List<Obj> _objList;
private Foo()
{
_objList = new List<Obj>();
}
public static Foo Instance
{
get
{
if (_instance == null)
{
lock (syncRoot)
{
_instance = new Foo();
}
}
return _instance;
}
}
public void AddObjToList(Obj _object)
{
lock (_instance)
{
_objList.Add(_object);
}
}
public void FindAndRemoveObj(string id)
{
lock (_instance)
{
Obj _object = null;
_object= _objList.FirstOrDefault(t => t.UniKey == id);
if (_object!= null)
{
_objList.Remove(object);
}
}
}
}
The first time that a class get the instance of this class it will return a new/clean instace of foo class, as expected, and then populating the list however a second class that will remove itens from the same list is receveing an new instance with an empty list.
This code has the lock in the wrong place:
if (_instance == null)
{
lock (syncRoot)
{
_instance = new Foo();
}
}
As thread 1 creates _instance, a second thread will block on the lock, then create _instance anew when it is released.
Another thing to be careful about it that you should never rely on static variables in IIS across server lookups. The application pool can be recycled at any time.
The conclusion was that the asp.net is creating new instances of the domain and that causes a new singleton object each time. I have searched how to sync objects between domains but that is too "workaround" for me, so I decided to add a boolean column that update the value with the confirmation or failure.
Thanks everyone

What is the correct way to dispose elements held inside a ThreadLocal<IDisposable>?

When you use a ThreadLocal<T> and T implements IDisposable, how are you supposed to dispose of the members being held inside of the ThreadLocal?
According to ILSpy, the Dispose() and Dispose(bool) methods of ThreadLocal are
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
int currentInstanceIndex = this.m_currentInstanceIndex;
if (currentInstanceIndex > -1 && Interlocked.CompareExchange(ref this.m_currentInstanceIndex, -1, currentInstanceIndex) == currentInstanceIndex)
{
ThreadLocal<T>.s_availableIndices.Push(currentInstanceIndex);
}
this.m_holder = null;
}
It does not appear that ThreadLocal attempts to call Dispose on its child members. I can't tell how to reference each thread it internally has allocated so I can take care of it.
I ran a test with the following code, the class is never disposed
static class Sandbox
{
static void Main()
{
ThreadLocal<TestClass> test = new ThreadLocal<TestClass>();
test.Value = new TestClass();
test.Dispose();
Console.Read();
}
}
class TestClass : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool Disposing)
{
Console.Write("I was disposed!");
}
}
I had a look at the code in ThreadLocal<T> to see what the current Dispose is doing and it appears to be a lot of voodoo. Obviously disposing of thread-related stuff.
But it doesn't dispose of the values if T itself is disposable.
Now, I have a solution - a ThreadLocalDisposables<T> class, but before I give the full definition it's worth thinking about what should happen if you wrote this code:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>();
tl.Value = myEdr1;
tl.Value = myEdr2;
tl.Dispose();
Should both myEdr1 & myEdr2 both be disposed? Or just myEdr2? Or should myEdr1 be disposed when myEdr2 was assigned?
It's not clear to me what the semantics should be.
It is clear to me, however, that if I wrote this code:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>(
() => new ExpensiveDisposableResource());
tl.Value.DoSomething();
tl.Dispose();
Then I would expect that the resource created by the factory for each thread should be disposed of.
So I'm not going to allow the direct assignment of the disposable value for ThreadLocalDisposables and only allow the factory constructor.
Here's ThreadLocalDisposables:
public class ThreadLocalDisposables<T> : IDisposable
where T : IDisposable
{
private ThreadLocal<T> _threadLocal = null;
private ConcurrentBag<T> _values = new ConcurrentBag<T>();
public ThreadLocalDisposables(Func<T> valueFactory)
{
_threadLocal = new ThreadLocal<T>(() =>
{
var value = valueFactory();
_values.Add(value);
return value;
});
}
public void Dispose()
{
_threadLocal.Dispose();
Array.ForEach(_values.ToArray(), t => t.Dispose());
}
public override string ToString()
{
return _threadLocal.ToString();
}
public bool IsValueCreated
{
get { return _threadLocal.IsValueCreated; }
}
public T Value
{
get { return _threadLocal.Value; }
}
}
Does this help?
In .NET 4.5, the Values property was added to ThreadLocal<> to deal with the problem of manually managing the lifetime of ThreadLocal objects. It returns a list of all current instances bound to that ThreadLocal variable.
An example using a Parallel.For loop accessing a ThreadLocal database connection pool was presented in this MSDN article. The relevant code snippet is below.
var threadDbConn = new ThreadLocal<MyDbConnection>(() => MyDbConnection.Open(), true);
try
{
Parallel.For(0, 10000, i =>
{
var inputData = threadDbConn.Value.GetData(i);
...
});
}
finally
{
foreach(var dbConn in threadDbConn.Values)
{
dbConn.Close();
}
}
Normally when you don't explicitly dispose of a class that holds an unmanaged resource, the garbage collector will eventually run and dispose of it. For this to happen, the class has to have a finalizer that disposes of its resource. Your sample class doesn't have a finalizer.
Now, to dispose of a class that's held inside a ThreadLocal<T> where T is IDisposable you also have to do it yourself. ThreadLocal<T> is just a wrapper, it won't attempt to guess what's the correct behavior for its wrapped reference when it is itself disposed. The class could, e.g., survive its thread local storage.
This is related to ThreadLocal<> and memory leak
My guess is because there is no IDisposable constraint on T, it is assumed that the user of ThreadLocal<T> will dispose of the local object, when appropriate.
How is the ThreadLocal.Dispose method itself getting called? I would expect that it would most likely be within something like a "using" block. I would suggest that one wrap the "using" block for the ThreadLocal with a "using" block for the resource that's going to be stored there.
MSDN reference states that the ThreadLocal values should be disposed by the thread using them once its done. However in some instances such as event threading using a thread pool A thread may use the value and go off to do something else and then come back to the value N number of times.
Specific example is where I want an Entity Framework DBContext to persist across the lifespan of a series of service bus worker threads.
I've written up the following class which I use in these instances:
Either DisposeThreadCompletedValues can be called manually every so often by another thread or the internal monitor thread can be activated
Hopefully this helps?
using System.Threading;
public class DisposableThreadLocal<T> : IDisposable
where T : IDisposable
{
public DisposableThreadLocal(Func<T> _ValueFactory)
{
Initialize(_ValueFactory, false, 1);
}
public DisposableThreadLocal(Func<T> _ValueFactory, bool CreateLocalWatcherThread, int _CheckEverySeconds)
{
Initialize(_ValueFactory, CreateLocalWatcherThread, _CheckEverySeconds);
}
private void Initialize(Func<T> _ValueFactory, bool CreateLocalWatcherThread, int _CheckEverySeconds)
{
m_ValueFactory = _ValueFactory;
m_CheckEverySeconds = _CheckEverySeconds * 1000;
if (CreateLocalWatcherThread)
{
System.Threading.ThreadStart WatcherThreadStart;
WatcherThreadStart = new ThreadStart(InternalMonitor);
WatcherThread = new Thread(WatcherThreadStart);
WatcherThread.Start();
}
}
private object SyncRoot = new object();
private Func<T> m_ValueFactory;
public Func<T> ValueFactory
{
get
{
return m_ValueFactory;
}
}
private Dictionary<Thread, T> m_InternalDict = new Dictionary<Thread, T>();
private Dictionary<Thread, T> InternalDict
{
get
{
return m_InternalDict;
}
}
public T Value
{
get
{
T Result;
lock(SyncRoot)
{
if (!InternalDict.TryGetValue(Thread.CurrentThread,out Result))
{
Result = ValueFactory.Invoke();
InternalDict.Add(Thread.CurrentThread, Result);
}
}
return Result;
}
set
{
lock (SyncRoot)
{
if (InternalDict.ContainsKey(Thread.CurrentThread))
{
InternalDict[Thread.CurrentThread] = value;
}
else
{
InternalDict.Add(Thread.CurrentThread, value);
}
}
}
}
public bool IsValueCreated
{
get
{
lock (SyncRoot)
{
return InternalDict.ContainsKey(Thread.CurrentThread);
}
}
}
public void DisposeThreadCompletedValues()
{
lock (SyncRoot)
{
List<Thread> CompletedThreads;
CompletedThreads = new List<Thread>();
foreach (Thread ThreadInstance in InternalDict.Keys)
{
if (!ThreadInstance.IsAlive)
{
CompletedThreads.Add(ThreadInstance);
}
}
foreach (Thread ThreadInstance in CompletedThreads)
{
InternalDict[ThreadInstance].Dispose();
InternalDict.Remove(ThreadInstance);
}
}
}
private int m_CheckEverySeconds;
private int CheckEverySeconds
{
get
{
return m_CheckEverySeconds;
}
}
private Thread WatcherThread;
private void InternalMonitor()
{
while (!IsDisposed)
{
System.Threading.Thread.Sleep(CheckEverySeconds);
DisposeThreadCompletedValues();
}
}
private bool IsDisposed = false;
public void Dispose()
{
if (!IsDisposed)
{
IsDisposed = true;
DoDispose();
}
}
private void DoDispose()
{
if (WatcherThread != null)
{
WatcherThread.Abort();
}
//InternalDict.Values.ToList().ForEach(Value => Value.Dispose());
foreach (T Value in InternalDict.Values)
{
Value.Dispose();
}
InternalDict.Clear();
m_InternalDict = null;
m_ValueFactory = null;
GC.SuppressFinalize(this);
}
}

Categories