zoukankan      html  css  js  c++  java
  • 设计模式-单例模式

    单例模式

    单线程中可以这样使用

    单例模式:顾名思义,就是在程序中某类只允许有一个实例。这样我们只需要在该类的内部做点手脚即可。

     1 public class SingleTon
     2     {
     3         //创建私有的静态字段
     4         private static SingleTon singeTon;
     5 
     6         //私有构造函数 这样外面就不能通过new的方式创建该类的实例了
     7         private SingleTon()
     8         {
     9         }
    10         //在单线程中可以这样使用 静态的方法返回实例
    11         public static SingleTon CreateSingleTon()
    12         {
    13             if (singeTon==null)
    14             {
    15                 singeTon=new SingleTon();
    16             }
    17             return singeTon;
    18         }
    19     }
    View Code


    上述代码在单线程中没有问题。但是在多线程中就会创建多个实例。这样我们需要给类的内部加上标志位,然后上锁。

    多线程中的单例模式

    同上面的模式差不多,只是多了一个用于上锁的对象

     /// <summary>
        /// 多线程下创建单例
        /// </summary>
        public class ThreadSingleTon
        {
           //同样使用静态的该类字段
            private static ThreadSingleTon threadSingleTon;
            //创建一个静态只读的标志位,用于上锁
            private static readonly object o=new object();
            //为了外界不能直接new,同样使用私有构造函数
            private ThreadSingleTon()
            {
                
            }
            /// <summary>
            /// 学名:该类访问统一入口,实际就是一个该类的静态方法,返回该类的实例
            /// </summary>
            /// <returns></returns>
            private static ThreadSingleTon createThreadSingleTon()
            {
                //当第一个线程访问的时候,会对o对象上锁。
                //当第二个线程访问的时候,会对o对象检查 状态,如果上锁,该线程会挂起,等待第一个线程解锁
                //当lock语句运行完之后(线程运行完之后),会对o对象解锁。
                lock (o)
                {
                    if (threadSingleTon==null)
                    {
                        threadSingleTon=new ThreadSingleTon();
                    }
                }
                return threadSingleTon;
            }
        }
    View Code

    上面这种解决方案确实可以解决多线程的问题,但是上面代码对于每个线程都会对线程辅助对象locker加锁之后再判断实例是否存在,对于这个操作完全没有必要的,因为当第一个线程创建了该类的实例之后,后面的线程此时只需要直接判断(uniqueInstance==null)为假,此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销,损失了性能,为了改进上面实现方式的缺陷,我们只需要在lock语句前面加一句(uniqueInstance==null)的判断就可以避免锁所增加的额外开销,这种实现方式我们就叫它 “双重锁定”。

    双重锁定单例模式

    public class DoubleCheckSingleTon
        {
            //同样使用静态的该类字段
            private static DoubleCheckSingleTon doubleCheckSingleTon;
            //创建一个静态只读的标志位,用于上锁
            private static readonly object o=new object();
            //为了外界不能直接new,同样使用私有构造函数
            private DoubleCheckSingleTon()
            {
            }
            /// <summary>
            /// 学名:该类访问统一入口,实际就是一个该类的静态方法,返回该类的实例
            /// </summary>
            /// <returns></returns>
            private static DoubleCheckSingleTon CreateDoubleCheckSingleTon()
            {
                //当第一个线程访问的时候,会对o对象上锁。
                //当第二个线程访问的时候,会对o对象检查 状态,如果上锁,该线程会挂起,等待第一个线程解锁
                //当lock语句运行完之后(线程运行完之后),会对o对象解锁。
                //只需要在检查一遍,就是双重锁定
                if (doubleCheckSingleTon==null)
                {
                    lock (o)
                    {
                        if (doubleCheckSingleTon == null)
                        {
                            doubleCheckSingleTon = new DoubleCheckSingleTon();
                        }
                    }
                }
                return doubleCheckSingleTon;
            }
        }
    View Code
  • 相关阅读:
    无线网络的切换bat
    远程桌面远程服务器拷贝失灵 解决方法
    不能将 Null 值赋给类型为 (不可为 null 的值类型)的成员。解决方法
    应该改变面向对象的说法
    Windows 2012 装 Remote Desktop Organizer 无法连接到其他远程服务器
    JavaScript 运行时错误: 无法获取未定义或 null 一种解决方案
    ssd硬盘u盘装win7扩展文件时0x80070570错误
    swfit-小知识Demo
    ios-简单算法
    swfit-扩展语法
  • 原文地址:https://www.cnblogs.com/alua/p/3396147.html
Copyright © 2011-2022 走看看