单例模式2

一般单例模式如下:

class Singleton
{
public:
static Singleton *instance (void)
{
if (instance_ == 0)
// Critical section.
instance_ = new Singleton;
return instance_;
}
void method (void);
// Other methods and members omitted.
private:
static Singleton *instance_;
};

 

      应用代码在使用单例对象提供的操作前,通过调用静态的instance方法来获取单例对象的引用,如下所示:       Singleton::instance ()->method (); 

      但是一般的单例模式不适用于多线程中:例如,如果在并行主机上运行的多个线程在单例对象初始化之前同时调用Singleton::instance方法,Singleton的构造函数将被调用多次,这是因为多个线程将在上面展示的临界区中执行new singleton操作。临界区是一个必须遵守下列定式的指令序列:当一个线程/进程在临界区中运行时,没有其他任何线程/进程会同时在临界区中运行。在这个例子中,单例的初始化过程是一个临界区,违反临界区的原则,在最好的情况下将导致内存泄漏,最坏的情况下,如果初始化过程不是幂等的(idempotent.),将导致严重的后果。

       通常的陷阱和弊端。实现临界区的通常方法是在类中增加一个静态的Mutex对象。这个Mutex保证单例的分配和初始化是原子操作,如下:

class Singleton
{
public:
static Singleton *instance (void)
{
// Constructor of guard acquires lock_ automatically.
Guard guard (lock_);
// Only one thread in the critical section at a time.
if (instance_ == 0)
instance_ = new Singleton;
return instance_;
// Destructor of guard releases lock_ automatically.
}
private:
static Mutex lock_;
static Singleton *instance_;
};

        普通加锁引起的开销:即使这个临界区只是被使用了一次,但是每个对instance方法的调用都必须获取和释放lock_。虽然现在这个实现是线程安全的,但过多的加锁负载是不能被接受的。

        解决这个问题更好的方法是使用Double Checked Locking。它是一种用于清除不必要加锁过程的优化模式。如下:

class Singleton
{
public:
static Singleton *instance (void)
{
// First check
if (instance_ == 0)
{
// Ensure serialization (guard constructor acquires lock_).
Guard guard (lock_);
// Double check.
if (instance_ == 0)
instance_ = new Singleton;
}
return instance_;
// guard destructor releases lock_.
}
private:
static Mutex lock_;
static Singleton *instance_;
};

         第一个获取lock_的线程将构建Singleton,并将指针分配给instance_,后续调用instance方法的线程将发现instance_ != 0,于是将跳过初始化过程。如果多个线程试图并发初始化Singleton,第二个检测件阻止竞争条件的发生。在上面的代码中,这些线程将在lock_上排队,当排队的线程最终获取lock_时,他们将发现instance_ != 0于是将跳过初始化过程。

        上面Singleton::instance的实现仅仅在Singleton首次被初始化时,如果有多个线程同时进入instance方法将导致加锁负载。在后续对Singleton::instance的调用因为instance_ != 0而不会有加锁和解锁的负载。 通过增加一个mutex和一个二次条件检测,标准的单例实现可以是线程安全的,同时不会产生过多的初始化加锁负载。

适应性

> 当一个应用具有下列特征时,可以使用Double Checked Locking优化模式:
1、应用包含一个或多个需要顺序执行的临界区代码。
2、多个线程可能潜在的试图并发执行临界区。
3、临界区仅仅需要被执行一次。
4、在每一个对临界区的访问进行加锁操作将导致过多加锁负载。
5、在一个锁的范围内增加一个轻量的,可靠的条件检测是可行的。

ACE单例模式头文件:

template <class TYPE, class ACE_LOCK>
class ACE_Singleton : public ACE_Cleanup
{
public:
  /// Global access point to the Singleton.
  static TYPE *instance (void);

  /// Cleanup method, used by @c ace_cleanup_destroyer to destroy the
  /// ACE_Singleton.
  virtual void cleanup (void *param = 0);

  /// Explicitly delete the Singleton instance.
  static void close (void);

  /// Dump the state of the object.
  static void dump (void);

protected:
  /// Default constructor.
  ACE_Singleton (void);

  /// Contained instance.
  TYPE instance_;

#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES)
  /// Pointer to the Singleton (ACE_Cleanup) instance.
  static ACE_Singleton<TYPE, ACE_LOCK> *singleton_;
#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */

  /// Get pointer to the Singleton instance.
  static ACE_Singleton<TYPE, ACE_LOCK> *&instance_i (void);
};
之后这样用即可:

typedef ACE_Singleton<MYClass,ACE_Null_Mutex> MYClassSingleton;
#define MySingleton MYClassSingleton::instance() 
ACE instance实现:

template <class TYPE, class ACE_LOCK> TYPE *
ACE_Singleton<TYPE, ACE_LOCK>::instance (void)
{
    ACE_TRACE ("ACE_Singleton<TYPE, ACE_LOCK>::instance");

    ACE_Singleton<TYPE, ACE_LOCK> *&singleton = ACE_Singleton<TYPE, ACE_LOCK>::instance_i ();

    // Perform the Double-Check pattern...
    if (singleton == 0)
    {
          static ACE_LOCK *lock = 0;
          if (ACE_Object_Manager::get_singleton_lock (lock) != 0)
            // Failed to acquire the lock!
            return 0;

          ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0);

          if (singleton == 0)
          {
              ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0);

              // Register for destruction with ACE_Object_Manager.
              ACE_Object_Manager::at_exit (singleton);
           }
    }
  return &singleton->instance_;
}
instance_i实现:

template <class TYPE, class ACE_LOCK> ACE_Singleton<TYPE, ACE_LOCK> *&
ACE_Singleton<TYPE, ACE_LOCK>::instance_i (void)
{
  static ACE_Singleton<TYPE, ACE_LOCK> *singleton_ = 0;
  return singleton_;
}
设计模式还是应该学习学习的...

参考:学步园(http://www.xuebuyuan.com/751865.html#)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值