单例模式(对象创建型)c++
2014-02-23 20:59
316 查看
单例模式是:保证一个类仅有一个实例,并提供该一个访问它的全局访问点。
通常可以让一个全局变量是的一个对象被访问,但它不能防止你实例化多个对象。一个好的方法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建(将构造方法定义为私有的或保护的),并且提供一个访问该实例的方法(static方法)。这个实例是类的static变量,对于这个类只有一份。取得实例的方法是静态的,因为构造函数是私有的,所以只能通过类对象直接获得,所以方法也只能定义为静态的。不然无法获得实例。
单例模式最基本的分为两种:饿汉式、懒汉式
饿汉模式是:自己被加载时就将自己实例化。即定义时直接定义为类的一个对象。
另外因为定义的静态变量pInstance是一个指针,可以将一个指向Singleton子类的指针赋给这个变量。
这种是懒汉式单例类:即第一次被引用时,才将自己实例化。即pInstance被初始化为NULL, 而实际初始化是在函数中。懒汉式单例模式存在的问题是,当多线程环境下会出现同步问题,需要控制。
以下为饿汉懒汉实现代码:
为了解决懒汉式的多线程同步问题,加入锁,使用了互斥量,下面是实现代码:
以上是目前所学到的单例模式的内容。以后会不定时再补充~~
通常可以让一个全局变量是的一个对象被访问,但它不能防止你实例化多个对象。一个好的方法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建(将构造方法定义为私有的或保护的),并且提供一个访问该实例的方法(static方法)。这个实例是类的static变量,对于这个类只有一份。取得实例的方法是静态的,因为构造函数是私有的,所以只能通过类对象直接获得,所以方法也只能定义为静态的。不然无法获得实例。
单例模式最基本的分为两种:饿汉式、懒汉式
饿汉模式是:自己被加载时就将自己实例化。即定义时直接定义为类的一个对象。
另外因为定义的静态变量pInstance是一个指针,可以将一个指向Singleton子类的指针赋给这个变量。
这种是懒汉式单例类:即第一次被引用时,才将自己实例化。即pInstance被初始化为NULL, 而实际初始化是在函数中。懒汉式单例模式存在的问题是,当多线程环境下会出现同步问题,需要控制。
以下为饿汉懒汉实现代码:
////单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点 #include <iostream> using namespace std; //这种是饿汉式单例模式,即在类被构造出来后就将实例构造出来, //会提前占用系统资源 class HungrySingleton { public: //这种是饿汉式单例模式,即在类被构造出来后就将实例构造出来, //会提前占用系统资源 static HungrySingleton *getInstance() { return instance; } private: HungrySingleton() {} static HungrySingleton* instance; }; //这里是关键,直接初始化为类的对象,因为是类内数据,所以可以调用构造函数 HungrySingleton* HungrySingleton::instance = new HungrySingleton; //这种是懒汉式单例模式,即在使用时才将实例构造出来, //但这个会出现线程同步问题。 class LazySingleton { public: //函数必须是静态的,否则无法访问 static LazySingleton *getInstance() { //如果两个线程同时进入getinstance,同时执行,则有两个实例被构造出来 if (instance == NULL) instance = new LazySingleton(); return instance; } private: //构造函数私有的,不能再外部定义实例 LazySingleton() {} static LazySingleton* instance; }; //初始化为0 LazySingleton* LazySingleton::instance = 0; int main() { HungrySingleton *h1 = HungrySingleton::getInstance(); HungrySingleton *h2 = HungrySingleton::getInstance(); cout << "饿汉式单例模式运行结果:" << endl; if (h1 == h2) cout << "是同一个对象" << endl; LazySingleton *h3 = LazySingleton::getInstance(); LazySingleton *h4 = LazySingleton::getInstance(); cout << "懒汉式单例模式运行结果:" << endl; if (h3 == h4) cout << "是同一个对象" << endl; return 0; }
为了解决懒汉式的多线程同步问题,加入锁,使用了互斥量,下面是实现代码:
#include <iostream> #include <pthread.h> using namespace std; //解决懒汉式单例模式的多线程同步问题,即在new对象前加上锁,锁的实现在 //linux下采用mutex就够了,因为与顺序无关,只要保证一个时间只有一个线程就行了 class ThreadLazySingleton { public: static ThreadLazySingleton* getInstance(pthread_mutex_t mutex) { if (instance == NULL) { pthread_mutex_lock(&mutex); //双重检查,因为如果有两个线程同时通过第一个条件判断,进入到 //内部条件,然后一个线程先申请到互斥量,之后如果为NULL,创建, //但它退出后,已经分配了一个,所以必须再次重新判断一次是否为 //NULL,否则会再次分配一个对象。 if (instance == NULL) { instance = new ThreadLazySingleton; cout << "getInstance():" << instance << endl; } pthread_mutex_unlock(&mutex); return instance; } } private: ThreadLazySingleton() {} static ThreadLazySingleton *instance; }; ThreadLazySingleton* ThreadLazySingleton::instance = NULL; void *th_fn1(void *args) { cout << "线程" << pthread_self() << "开始运行" << endl; pthread_mutex_t *mutex = (pthread_mutex_t*)args; ThreadLazySingleton *p = ThreadLazySingleton::getInstance(*mutex); cout << p << endl; pthread_exit((void*)p); } int main() { pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); //初始化互斥量 int err; pthread_t tid1, tid2; ThreadLazySingleton* p1; ThreadLazySingleton* p2; err = pthread_create(&tid1, NULL, th_fn1, &mutex); if (err != 0) cout << "创建线程" << tid1 << "错误!" << endl; err = pthread_create(&tid2, NULL, th_fn1, &mutex); if (err != 0) cout << "创建线程" << tid2 << "错误!" << endl; pthread_join(tid1, (void**)&p1); pthread_join(tid2, (void**)&p2); //pthread_mutex_destory(&mutex); if (p1 == p2) cout << "同一个对象,同步正确" << endl; cout << p1 <<" " << p2 << endl; return 0; }
以上是目前所学到的单例模式的内容。以后会不定时再补充~~
相关文章推荐
- 【c++】PAT (Advanced Level)1009. Product of Polynomials (25)
- SkipList 跳表
- C++ 重载、重写、重定义
- 单片机数字钟
- C++中的指针常量和常量指针
- C++中的内存分配
- 直流电机
- C++中各种不同的new和delete
- C++ new一次,delete多次探讨
- [C++学习历程]Visual Studio 2010 中文旗舰版 安装
- [C++学习历程]Visual Studio 2010 中文旗舰版 安装
- [C++学习历程]Visual Studio 2010 中文旗舰版 安装
- 求子数组的最大和 C++实现
- C++输入一行字符串
- c++字符串详解(转)
- C++中临时量做参数的特点
- C++面试
- c/c++内存分配与内存对齐全面探讨
- 原型模式 c++(对象创建型模式)
- LeetCode题解汇总(C++ Java Python,含题目翻译)