单例模式

单线程中可以这样使用

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

 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

 

 

posted on 2013-10-30 10:25  已经超神  阅读(380)  评论(0编辑  收藏  举报