找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 4147|回复: 0

单体中的锁

[复制链接]
发表于 2008-9-21 15:05:35 | 显示全部楼层 |阅读模式
单体模式想必大家都很熟悉, 该模式的设计要点就是构造函数是私有或者保护的, 只能通过一个接口来构造它的一个实例, 从而保证系统范围内只有该类的一个实例对象, 实例如下:
class Singleton
{
public:
static Singleton* instance()
{
  if(NULL == m_pInstance)
  {
   m_pInstance = new Singleton();
  }
  return m_pInstance;
}
public:
//其他的单体服务接口
private:
Singleton()
{
  //初始化操作
}
static Singleton* m_pInstance;
}
但是上面的代码存在问题, 你看出来了吗?
在单线程环境下, 该代码是安全的, 但是移置到多线程环境下, 就会有隐患, 因为m_pInstance是静态成员变量, 在多个线程对它访问时需要同步.
如果多个线程同时调用该类的instance()接口, 就会出现内存泄漏.
我们可以在此增加一个锁成员变量, 来对它进行同步保护.
基于单线程和多线程之间的移植问题, 我们把该锁变量的类型参数化
template <class LOCK>
class Singleton
{
public:
static Singleton* instance()
{
  Guard<LOCK> temp(m_lock);   //关于Guard请参考我上篇贴
  if(NULL == m_pInstance)
  {
   m_pInstance = new Singleton();
  }
  return m_pInstance;
}
public:
//其他的单体服务接口
private:
Singleton()
{
  //初始化操作
}
static Singleton* m_pInstance;
static LOCK       m_lock;
}
这样安全了, 但是效率方面呢? 为了访问这个单体的服务, 每次访问instance()接口都要进行一次锁定操作, 效率大打折扣.
这样我们就要想了, 最好是在第一次初始化的时候需要锁定, 以后就可以直接访问了, 下面是改善后的代码
template <class LOCK>
class Singleton
{
public:
static Singleton* instance()
{
  if(NULL == m_pInstance)
  {
   Guard<LOCK> temp(m_lock); // 关于Guard请参考我上一篇贴
   if(NULL == m_pInstance)
   {
    m_pInstance = new Singleton();
   }
  }
  return m_pInstance;
}
public:
//其他的单体服务接口
private:
Singleton()
{
  //初始化操作
}
static Singleton* m_pInstance;
static LOCK       m_lock;
}
这样在访问instance的时候就会进行2次检测, 既保证了同步资源m_pInstace的安全, 同时又没又损失效率, 一举两得.
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-24 10:18 , Processed in 0.020783 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表