首页 > 代码库 > 关于“单例模式”的另外一种实现

关于“单例模式”的另外一种实现

  传统单例模式的实现有懒汉、饿汉等模式,也有双锁机制(防止不必要的线程再度进入锁的临界区实例化单例模式的全局变量)。不过据说(未经考证)在VS中CPU开启“out-of-order execution”,仍然会导致出问题,原因在于:

  我们假设a和b线程同时试图初始化单例模式的全局变量,a先进入方法获得了锁,b慢了一拍,判断全局变量!=null之后只能徘徊在外边直到a好了位置。我们设想a线程初始化应该的步骤:

       1)调用构造函数,产生实例对象。

   2)为全局变量分配栈和堆上的空间。

  3)将全局变量指向产生的实例对象。

  但是,可惜的是,一旦该优化开启之后,编译器变得“不听话了”,它会先1:为实例对象分配好空间,然后2:直接把全局变量指针指向该空间,最后3:才调用构造函数去“充实”实例。设想一下,如果是这样的话,b徘徊在外边,等到线程a刚完成2,b就发现全局变量已经不为null了!但是实例化构造函数尚未调用(或者调用中),结果会如何?!

  因此,如果没有必要延时加载,用“饿汉模式”或者直接写入静态构造函数的“懒汉模式”最好,否则需要根据动态反射等机制的,建议使用InternLock,类似以下代码:

 if(_instance==null)
            {
                Interlocked.CompareExchange<AbsDatabaseFactory>(ref _instance, (AbsDatabaseFactory)Assembly.LoadFile(pathwithFileName).CreateInstance(classTypeName), null);
                Instance = _instance;
                ConnectionString = connectionString;
            }

  考虑到这是微软的方法,因此速度特快(尽管也有可能冒着“诞生几个类”的可能),但是应该不会出现错误的。大家以为呢?