I have a singleton class similar to this
public class Singleton
{
private static Singleton m_instance;
private Timer m_timer;
private static List<CustomObject> m_cacheObjects;
private Singleton()
{
m_cacheObjects = new List<CustomObject>();
m_timer= new Timer(MyTimerCallBack,
null,
TimeSpan.FromSeconds(60),
TimeSpan.FromSeconds(60));
}
public static Singleton Instance
{
get
{
if (m_instance == null)
{
m_instance = new Singleton();
}
return m_instance;
}
}
private void MyTimerCallBack(object state)
{
//******** Update the list by interval here ******************
m_cacheObjects = UpdateTheList();
}
public void CallMe()
{
foreach (CustomObject obj in m_cacheObjects)
{
// do something here based on obj
// The question is, does the m_cacheObjects is thread safe??
// what happen if the m_cacheObjects is changed
// during the loop interation?
}
}
}
The CallMe method will be called by web service:
[WebMethod]
public void CallMeWebService()
{
Singleton.Instance.CallMe();
}
The questions: 1) Is the m_cacheObjects is thread safe? what happen if the m_cacheObjects is changed(because of the timer) during the loop interation (in the CallMe() )?
2) Is a new thread will be created when the Webservice CallMeWebService() is being called?
1: No, a static list is not automatically thread-safe; you must protect m_cacheObjects
manually
2: That is an implementation detail; at first glance it looks like it exposes itself as a sync method, but how it does that is entirely up to it
Actually, your static initialization isn't thread-safe either; I could brute-force a scenario where two different Singleton
instances were used. It would take repetition to produce it, but it would happen.
Frankly, unless you have a really good reason not to, the simplest but safest singleton pattern is simply:
private static readonly Singleton m_instance = new Singleton();
我建议你在Jon Skeets上发表关于如何在http://csharpindepth.com/Articles/General/Singleton.aspx上创建线程安全单例的文章
//using System.Runtime.CompilerServices;
private static volatile Singelton _instance;
public static Singelton Instance
{
[MethodImpl(MethodImplOptions.Synchronized)]
get
{
if (_instance == null)
{
_instance = new Singelton();
}
return _instance;
}
}
Explain:
[MethodImpl(MethodImplOptions.Synchronized)] This will tell the compiler that the access to "Instance" is "Synchronized" so the system take care about the calls to this Parameter.
This is Thread-Safe.
EDIT: (Also, the "Lock()" examples are not safe! Coz, u can disable the thread Safety with "Monitor.Exit(Singleton);")
This is a pretty good resource on how to implement the singleton pattern in a thread safe way: http://msdn.microsoft.com/en-us/library/ff650316.aspx
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
This simply makes sure that there will never be more than one instance. You also need to apply locking for your custom method.
public void CallMe()
{
lock (syncRoot)
{
foreach (CustomObject obj in m_cacheObjects)
{
// do something here based on obj
}
}
}
It is not thread safe.
I believe i would use a lock in both 'MyTimerCallBack' and 'CallMe' methods
1) No, m_cacheObjects
is not thread-safe.
2) Yes, new thread will be created (well, it may not be new thread but rather thread taked from thread-pool).
You'll need to protect m_cacheObjects
with lock
statement. Also, in the CallMe method I'd recommend to create a local copy of m_cacheObjects
:
// create new field syncRoot
private static readonly object syncRoot = new object();
New CallMe method:
List<CustomObject> localCopy;
lock (syncRoot)
{
localCopy = new List<CustomObject>(m_cacheObjects);
}
foreach (var nextObject in localCopy)
{
// Do some work
}
And updated MyTimerCallBack
method:
lock (syncRoot)
{
m_cacheObjects = UpdateTheList();
}
And please also implement thread-safe Singleton (read other answers for details).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.