实现一个线程安全的单例模式
来源:互联网 发布:随机生成域名检测 编辑:程序博客网 时间:2024/06/06 03:14
一、单例模式
单例模式也叫单件模式。Singleton是一个非常常用的设计模式,几乎所有稍微大一些的程序都会使用它,所以构建一个高效的Singleton很重要。
1、单例类保证全局只有一个唯一实例对象
2、单例类提供获取这个唯一实例的接口。
我们都能想到一个简单的单例模式该怎样实现:构造函数声明为private或protec防止被外部函数实例化,内部保存一个private static的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例。
先看一段代码
class Singleton{public://获取唯一对象实例的接口函数static Singleton* GetInstance(){if(_sInstance==NULL){_sInstance=new Singleton();}return _sInstance;}//删除示例对象static void DelInstance(){if(_sInstance){delete _sInstance;_sInstance=NULL;}}void Print(){cout<<_data<<endl;}private://构造函数定义为私有,限制只能在类内创建对象Singleton():_data(0){}Singleton(const Singleton&);Singleton& operator=(const Singleton&);//指向实例的指针定义为静态私有,这样定义静态成员函数获取对象实例static Singleton* _sInstance;//单例类里面的数据int _data;}void TestSingleton(){TestSingleton::GetInstance()->Print();TestSingleton::DelInstance;}这个方法简单易懂,但是它是线程不安全的,如果两个线程同时调用_sInstance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误。当然我们也有线程安全的实现方法。
二、懒汉模式与饿汉模式
单例大约有两种实现方法:懒汉与饿汉。
*懒汉:顾名思义,不到万不得已就不回去实例化,也就是说在第一次用到类实例的时候才回去实例化。
*饿汉:与懒汉相反,它是饥不择食的,所以在单例类定义的时候就进行实例化。
两者的特点与选择要点:
*由于要进行线程同步,所以在访问量较大,或者可能访问的线程较多时采用饿汉实现,可以实现更好的性能。这是以空间换时间。
*在访问量较小时,可以实现懒汉模式。这是以时间换空间。
三、线程安全的的懒汉模式
*方法一:加锁的经典懒汉实现:
class singleton{protected:singleton(){pthread_mutex_init(&mutex);}private:static singleton* p;public:static pthread_mutex_t mutex;static singleton* instance();};pthread_mutex_t singleton::mutex;singleton* singleton::p=NULL;singleton* singleton::instance(){if(p==NULL){pthread_mutex_lock(&mutex);if(p==NULL){p=new singleton();}pthread_mutex_unlock(&mutex);}return p;}*方法二:内部静态变量的懒汉实现
这个方法也比较简单,在instance函数里定义一个静态的实例,也可以保证拥有唯一实例,在返回时只需要返回其指针就可以了。
class singleton{protected:singleton(){pthread_mutex_init(&mutex);}public:static pthread_mutex_t mutex;static singleton* instance();int a;};pthread_mutex_t singleton::mutex;singleton* singleton::instance(){pthread_mutex_lock(&mutex);static singleton obj;pthread_mutex_unlock(&mutex);return &obj;}
四、饿汉模式
线程安全本来就是安全的,不用加锁,因为在饿汉模式下,在单例类定义时就已经定义了一个对象,对类进行了初始化。后面不管哪个线程调用函数instance(),都只不过时返回一个对象的指针而已。所以是线程安全的,不需要在成员函数instance中加锁。
class singleton{protected:singleton(){}private:static singleton* p;public:static singleton* initance();int a;};singleton* singleton::p=new singleton;singleton* singleton::initance(){return p;}int main(){singleton* s=singleton::instance();s->a=10;return 0;}
- 怎么实现一个线程安全的单例模式呢?
- 实现一个线程安全的单例模式
- 实现一个单例模式的类,要求线程安全
- 写一个线程安全的单例模式
- 设计一个线程安全的单例(Singleton)模式
- 写一个线程安全的单例模式
- 一个线程安全的单例模式示例
- 写一个线程安全的单例模式
- 线程安全的单例模式的实现
- 线程安全的单例模式 的各种实现 总结
- 线程安全的单例模式的实现
- 实现单例模式的线程安全的类
- 单例模式的四种线程安全的实现
- 一种线程安全的单例模式实现
- 单例模式实现 线程安全的队列 处理
- C++实现线程安全的单例模式
- 这里实现定界加锁线程安全的单例模式
- C++线程安全的单例模式实现
- 2017.8.2——广搜(bfs)+队列的使用
- 并查集
- poj1845 逆元 因子和
- Linux命令集
- 牛顿法求解立方根
- 实现一个线程安全的单例模式
- PHP基础教程-09 浮点型变量
- Zeppelin源码分析-调度和资源分析(1)
- android 下创建一个sqlite数据库
- BZOJ1409 Password
- JAVA考核题-数据类型
- 使用栈实现进制转换、括号匹配的检验、行编辑程序
- Java基础——方法参数
- Zeppelin源码分析-调度和资源分析(2)