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

发布于 2024-11-17 00:41:38 字数 1016 浏览 5 评论 0原文

我有在多个线程中共享的单例类。为了防止多重访问问题,我在访问类的一个或另一个属性时使用 Lock 方法。问题是是否可以改进代码并将 Lock 方法放入单例类中,而不是每次在代码中访问类属性时都将其放入?

/* 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++;
}

I have singleton class which is shared in several threads. To prevent multiple access issues I use Lock method when accessing one or another property of the class. The question would be is it possible to improve code and put Lock method inside singleton class rather than putting it every time when the class property is accessed in code?

/* 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++;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

陌上青苔 2024-11-24 00:41:38

ServerStatus 应该维护自己的同步,而不是此类的外部客户端。话虽这么说,您需要重构 ServerStatus 并创建一些线程安全(带锁定)的方法:

删除这些属性: public List;活塞队列 { 得到;放; } 因为即使您可以锁定这些属性,您也无法控制客户端在获取实际的 PistonQueue 后执行的操作。

...并替换为以下方法(抱歉伪代码,我今天懒得去思考):

public PistonQueueAdd(string fullPath)
{
    lock(_serverStatusSyncRoot)
    {
        // ...
    }
}

ServerStatus should maintain its own synchronization, not external clients of this class. That being said, you'll need to refactor ServerStatus and create a few thread-safe (with locking) methods:

Remove these properties: public List<string> PistonQueue { get; set; } since even though you can lock inside these properties, you can't control what clients do once they get a hold of the actual PistonQueue.

...and replace with methods such as (sorry pseudo-code, I can't be bothered to think today):

public PistonQueueAdd(string fullPath)
{
    lock(_serverStatusSyncRoot)
    {
        // ...
    }
}
鸵鸟症 2024-11-24 00:41:38

如果您感兴趣的话,这是我使用的单例线程安全模式:

    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
}

This is the singleton thread-safe pattern I use in case you are interested:

    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
}
泪痕残 2024-11-24 00:41:38

恕我直言,这是单例中线程安全锁定的最终解决方案。来自它(列表中的第五个):

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();
    }
}

IMHO, this is the definitive solution for thread-safe locking in a singleton. From it (fifth on the list):

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();
    }
}
享受孤独 2024-11-24 00:41:38

这是相当常见的。与每个属性访问上的外部锁相比,在 getter/setter 中锁定/解锁更安全(您不能忘记这样做),也更方便(该锁不必在您使用该属性的任何地方都可以直接访问) 。

平均值,
马丁

This is fairly common. Locking/unlocking in the getters/setters is much safer, (you cannot forget to do it), and more convenient, (the lock does not have to be directly accessable everywhere you use the property), than an external lock on every property access.

Rgds,
Martin

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文