• Singleton模式之多线程


    一、引言

    自己也算是使用Singleton的老客户了,也明白如何写代码能最大限度的避免多线程产生多个实例。但是自己却很少遇到在多线程下使用Singleton,所以自己也是一知半解。

    今天正好有空,搞搞清楚这个问题。

    二、问题的产生

    请看如下代码:

    public class Animal
        {
            private static  Animal instance = null;
            private Animal()
            {
            }
            public static Animal getInstance()
            {
                if (instance == null)
                {
                    instance = new Animal();
                }
                return instance;
            }
        }
    

    经常看到有些网友这样写。这样写在大都数情况下挺适用的。我们知道操作系统为每个独立线程安排一些CPU时间。单CPU操作系统以轮转方式向线程提供时间片,每个线程在使用完时间片后交出控制,系统再将CPU时间片分配给下一个线程,如下代码,我将使某个线程睡眠模拟线程的时间片用完。代码如下:

      public static Animal getInstance()
            {
                if (instance == null)
                {
                    if (Thread.CurrentThread.Name == "Thread1")
                    {
                        Thread.Sleep(2000);//模拟Thread1的时间片用完了
               }
                    instance = new Animal();
                }
                return instance;
            }
    
     private void BeginThread()
            {
                Thread th = new Thread(this.Run){IsBackground=true};
                th.Name = "Thread1";
                th.Start();
                Thread th2 = new Thread(this.Run2) {IsBackground=true };
                th2.Name="Thread2";
                th2.Start();
            }
            private void Run()
            {
               Animal p1 = People.Instance;
            }
            private void Run2()
            {
               Animal p2 = People.Instance;
            }

    如上Animal p1与Animal p2就是不同的实例。

    当然了,这里只是模拟一下时间片的轮换,虽然是模拟但是却能很好的说明问题,上面的Singleton有问题,那么应该怎么写呢?

    我想有2个方法:

    方法一:锁机制

    public class Animal
        {
            private static  Animal instance = null;
            private static object sync = new object();
            private Animal()
            {
            }
            public static Animal getInstance()
            {
                if (instance != null)
                {
                    lock (sync)
                    {
                        if (instance == null)
                        {
                            instance = new Animal();
                        }
                    }
                }
                return instance;
            }
        }
    

    我们可以通过锁住部分代码,同时间只让一个线程执行。有人要问了:为什么最外面还要用 "if (instance != null)"

    因为同步操作执行时间长,也耗资源,在最外面加个判断能够更高效的实现Singleton.

    值得注意的是:对于NET的执行机制,编译后再执行,编译会微调我们的代码,既然微调那么很可能执行的逻辑就会改变,为了严格意义上执行如上代码,可以加上volatile关键字

    如:private static volatile Animal instance。

    方法二:如果使用NET进行开发,可以借助于静态构造器的功能

    public sealed class People
        {
            private People()
            {
            }
            public static readonly People Instance;
            static People()
            {
                Instance = new People();
            }
        }
    

    静态构造器自身就可以保证,多线程情况下,系统就可以保证只有一个执行。 使用readonly可以防止使用Instance=null设置实例。

    当然了,NET还有其他机制可以避免伪Sigleton,请大家能够给出。

  • 相关阅读:
    Numpy技巧
    Date
    Soulwail
    吴裕雄--天生自然python学习笔记:python 用 Open CV抓取脸部图形及保存
    吴裕雄--天生自然python学习笔记:python 用 Open CV 进行人脸识别
    吴裕雄--天生自然python学习笔记:人脸识别用到的特征文件haarcascade_frontalface_default.xml下载
    吴裕雄--天生自然python学习笔记:python OpenCV 基本绘图
    吴裕雄--天生自然python学习笔记:python用OpenCV 读取和显示图形
    吴裕雄--天生自然python学习笔记:python下载安装各种模块的whl文件网址
    吴裕雄--天生自然python学习笔记:python爬虫PM2.5 实时监测显示器
  • 原文地址:https://www.cnblogs.com/smallstone/p/1997666.html
Copyright © 2020-2023  润新知