所在的位置: C++ >> C++前景 >> C单列模式学到牛牛

C单列模式学到牛牛

北京医院治疗皮肤科 http://pf.39.net/bdfyy/bdfjc/160306/4781492.html

单例模式是一种最为常见的软件设计模式。单例模式要求:单例对象所在的类必须保证只能创建一个对象。单例模式在我们日常生活和软件开发中的应用比比皆是,比如:windows系统只有一个任务管理器,一个市只有一个市长。

  如何保证一个类最多只能创建一个对象呢?这个问题不能交由使用者去做处理,比如用全局变量。而应该由这个类的创建者在实现该类的时候考虑问题的解决。

  单例模式巧妙的使用C++成员权限,将构造函数和拷贝构造函数隐藏起来(private),从而有效限定使用中对对象的自由创建。然后开放一个(static)接口,通过静态方法创建对象,并在静态方法中限定对象的唯一创建。

  单例模式的创建方式一般有两种:懒汉式和饿汉式。

1.懒汉模式

懒汉:顾名思义,不到万不得已该类不会去实例化对象。将对象的示例推迟到需要该对象的时候。

//单例模式之懒汉模式

classSingleton{

public:

    staticSingleton*createSingleton(){  //static方法

      if(m_handler==nullptr){

        m_handler=newSingleton();

      }

      returnm_handler;

    }

private:

  Singleton();      //私有化构造函数

  ~Singleton();    //私有化析构函数

  Singleton(constSingleton);  //私有化拷贝构造函数,防止通过拷贝构造复制对象

  staticSingleton*m_handler;

};

Singleton*Singleton::m_handler=nullptr;

intmain()

{

  Singleton*ptr1=Singleton::createSingleton();

  Singleton*ptr2=ptr1-createSingleton();//ptr1和ptr2指向同一个对象

  return0;

}

2.饿汉模式

饿汉:单例类在创建类的时候就创建了对象。

//单例模式之饿汉模式

classSingleton{

public:

    staticSingleton*getSingleton(){

      returnm_handler;

    }

private:

  Singleton();      //私有化构造函数

  ~Singleton();    //私有化析构函数

  Singleton(constSingleton);  //私有化拷贝构造函数,防止通过拷贝构造复制对象

  staticSingleton*m_handler;

};

Singleton*Singleton::m_handler=newSingleton;    //类创建时,创建对象

intmain()

{

  Singleton*ptr1=Singleton::createSingleton();

  Singleton*ptr2=ptr1-createSingleton();//ptr1和ptr2指向同一个对象

  return0;

}

3.单例模式中的线程安全

前面我们考虑了单例模式的懒汉式和饿汉式,但是我们只考虑了普通单线程情况。如果考虑到多线程情况,那么上面的懒汉模式则不是线程安全的。而饿汉模式因为在编译阶段已经创建了对象,所有它是线程安全的。

如何解决懒汉模式的线程不安全呢?通常情况我们可以通过互斥锁解决临界资源的访问问题。

//单例模式之懒汉模式+线程安全

classSingleton{

public:

  staticSingleton*createSingleton(){  //static方法

    if(m_handler==nullptr){//解决访问效率问题

      pthread_mutex_lock(m_lock);

      if(m_handler==nullptr){

        m_handler=newSingleton();

      }

      pthread_mutex_unlock(m_lock);

      returnm_handler;

    }

  }

private:

  Singleton();      //私有化构造函数

  ~Singleton();    //私有化析构函数

  Singleton(constSingleton);  //私有化拷贝构造函数,防止通过拷贝构造复制对象

  staticSingleton*m_handler;

  staticpthread_mutex_tm_lock;

};

Singleton*Singleton::m_handler=nullptr;

pthread_mutex_tSingleton::m_lock=PTHREAD_MUTEX_INITIALIZER;

intmain()

{

  Singleton*ptr1=Singleton::createSingleton();

  Singleton*ptr2=ptr1-createSingleton();//ptr1和ptr2指向同一个对象

  return0;

}

上面例程通过互斥锁,看似解决了多线程中的临界资源互斥问题。但是实际上并非如此。具体问题如下:

上面代码中:m_handler=newSingleton();我们期望的执行顺序是:

(1)分配一段内存(2)构造对象,放入内存(3)m_handler存内存地址

但是实际执行可能是:

(1)分配一段内存(2)m_handler存内存地址(3)构造对象,放入内存

那么后面的情况可能导致,对象还没创建,但是已经被另外一个线程拿去使用了,这种情况可能导致严重错误。那么如何解决呢?大家可以思考一下。

文章来源:学到牛牛


转载请注明:http://www.aierlanlan.com/cyrz/3656.html

  • 上一篇文章:
  •   
  • 下一篇文章: