多线程应用程序中的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++;
}

多线程应用程序中的Singleton类,锁定建议

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