多线程应用程序中的Singleton类,锁定建议
本文关键字:锁定 Singleton 应用程序 多线程 | 更新日期: 2023-09-27 17:59:50
我有一个singleton类,它在几个线程中共享。为了防止多重访问问题,我在访问类的一个或另一个属性时使用Lock方法。问题是,是否可以改进代码并将Lock方法放入singleton类中,而不是每次在代码中访问类属性时都将其放入?
/* Class code*/
public class ServerStatus
{
private static ServerStatus _instance;
public static ServerStatus Instance
{
get { return _instance ?? (_instance = new ServerStatus()); }
set { _instance = value; }
}
ServerStatus()
{
PistonCount = 0;
PistonQueue = new List<string>();
ErrorList = new List<string>();
}
public int PistonCount { get; set; }
public List<string> PistonQueue { get; set; }
public List<string> ErrorList { get; set; }
}
/*Code for accessing class properties*/
private static readonly object Locker = new object();
/*Skip*/
lock (Locker)
{
ServerStatus.Instance.PistonQueue.Add(e.FullPath);
}
/*Skip*/
lock (Locker)
{
ServerStatus.Instance.PistonCount++;
}
ServerStatus
应该维护自己的同步,而不是此类的外部客户端。话虽如此,您需要重构ServerStatus
并创建几个线程安全(带锁定)方法:
删除这些属性:public List<string> PistonQueue { get; set; }
,因为即使您可以锁定在这些属性内部,但一旦客户端获得实际的PistonQueue
,您就无法控制它们的操作。
并替换为方法,例如(对不起,伪代码,我今天不想思考):
public PistonQueueAdd(string fullPath)
{
lock(_serverStatusSyncRoot)
{
// ...
}
}
这是我在您感兴趣的情况下使用的单线程安全模式:
public class DataAccess
{
#region Singleton
private static readonly object m_SyncRoot = new Object();
private static volatile DataAccess m_SingleInstance;
public static DataAccess Instance
{
get
{
if (m_SingleInstance == null)
{
lock (m_SyncRoot)
{
if (m_SingleInstance == null)
m_SingleInstance = new DataAccess();
}
}
return m_SingleInstance;
}
}
private DataAccess()
{
}
#endregion
}
IMHO,这是单例中线程安全锁定的最终解决方案。从中(排名第五):
public sealed class Singleton
{
private Singleton()
{
}
public static Singleton Instance { get { return Nested.instance; } }
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
这很常见。在getters/ssetters中锁定/解锁要比在每个属性访问上使用外部锁安全得多(你不能忘记这样做),也更方便(锁不必在你使用属性的任何地方都可以直接访问)。
Rgds,Martin