设计模式之:单例模式
来源:互联网 发布:lua调用linux c库 编辑:程序博客网 时间:2024/05/23 18:43
一个单例类的特点:
1、进程内只有唯一的类实例
不可以被随意构造(禁止任何形式的自行构造),在被使用时或使用前创建(前者为所谓懒汉式,后者为所谓饿汉式),进程结束时释放
2、多线程共用
内部资源访问控制需要锁互斥
具体的实现:
1、实现禁止构造:
出于不可以被随意构造(禁止任何形式的自行构造)的需要,单例基类需要禁止构造,实现方式为继承一个noncopyable基类
可以像下面这样的实现一个noncopyable,也可以继承boost的boost::noncopyable,推荐下面的方式。
下面的方式也是c++11对delete关键字的运用,禁止掉默认、复制构造函数和赋值运算符方法,使程序中无法创建单例类的实例。
class noncopyable {public: noncopyable() = delete; noncopyable(const noncopyable &) = delete; noncopyable &operator= (const noncopyable &) = delete; ~noncopyable() = default;};
按常用的懒汉式,一个单例基类的基本特性:
1. 在被使用时创建,多个线程使用也只会创建一次;
2. 进程退出时,释放掉实例
基于以上特性需要,实现方式分别为:
1. 使用pthread_once_t数据结构,保证在第一次使用时,多个线程只会有一个线程实际创建单例实例,其余线程则直接获取创建好的实例
2. 让每个单例类实例以静态指针变量存在,并重载类静态资源析构函数(__attribute__((destruct))修饰),这样,在进程退出自动调用静态变量析构方法时,释放掉单例内存
具体实现如下,
1. 模板类Singleton继承noncopyable实现禁止构造
2. public方法仅包括get,进程内线程只可以通过get方法获取单例类实例
3. 单例实例为类静态变量_instance,即每个单例类都有一个唯一的静态类实例
4. 同时每个单例类由静态变量_p_once控制只有一个线程会在单例类实例不存在时创建实例(调用类静态函数_construct),其他线程直接获取实例
5. 重载类的静态资源析构函数(__attribute__((destruct))修饰),在进程退出时,释放掉单例实例
template<class T> class Singleton : public noncopyable { Singleton(){} ~Singleton(){} static void _construct () { _instance = new T; } __attribute__((destruct)) static void _delete () { delete _instance; } static T *_instance; static pthread_once_t _p_once;public: static T * get () { pthread_once(&Singleton::_p_once, &Singleton::_construct); return _instance; }};template<class T> pthread_once_t Singleton<T>::_p_once = PTHREAD_ONCE_INIT;template<class T> T *Singleton<T>::_instance = nullptr;
3、实现一个单例类:
多线程均通过get方法获取单例实例即可。
由于多线程均操作同一个实例,所以单例类在资源非原子操作时要加互斥锁,如下:
class Resource { int a; std::atomic<int> b; std::mutex mtx;public: Resource(){} ~Resource(){} void Init () { std::cout << "init" << std::endl; } void Set (int _a) { std::unique_lock<std::mutex> lock(mtx); a = _a; } int Get () { int t; { std::unique_lock<std::mutex> lock(mtx); t = a; } return t; } void SetAtomic (int _b) { b = _b; } int GetAtomic () { return b; }};
4、测试:
std::vector<std::thread> ths(10); for (int i = 0; i < 10; i++) { ths[i] = std::thread([i] () { while (1) { std::random_device rd; int a = rd() % 100, b = rd() % 100; Resource *s = Singleton<Resource>::get(); int rawa = s->Get(), rawb = s->GetAtomic(); s->Set(a); s->SetAtomic(b); std::cout << "i am thread " << i << " get rawa " << rawa << " and get rawb " << rawb << " , set a " << a << " and set b " << b << "-----------------" << std::endl; std::chrono::microseconds duration(100); std::this_thread::sleep_for(duration); } }); } for (auto &i:ths) { i.join(); }
10个线程并发的读写单例类Resource的单例。
下图是测试的输出情况,验证是否发生多线程同步问题。
i am thread 5 get rawa 40 and get rawb 38 , set a 49 and set b 65-----------------i am thread 1 get rawa 49 and get rawb 65 , set a 43 and set b 25-----------------i am thread 3 get rawa 43 and get rawb 25 , set a 14 and set b 87-----------------i am thread 8 get rawa 14 and get rawb 87 , set a 46 and set b 54-----------------i am thread 7 get rawa 46 and get rawb 54 , set a 63 and set b 0-----------------i am thread 6 get rawa 63 and get rawb 0 , set a 21 and set b 26-----------------i am thread 5 get rawa 21 and get rawb 26 , set a 35 and set b 3-----------------i am thread 9 get rawa 35 and get rawb 3 , set a 57 and set b 39-----------------i am thread 2 get rawa 57 and get rawb 39 , set a 24 and set b 16-----------------i am thread 0 get rawa 24 and get rawb 16 , set a 94 and set b 65-----------------i am thread 1 get rawa 94 and get rawb 65 , set a 30 and set b 0-----------------i am thread 3 get rawa 30 and get rawb 0 , set a 76 and set b 35-----------------i am thread 8 get rawa 76 and get rawb 35 , set a 46 and set b 14-----------------i am thread 7 get rawa 46 and get rawb 14 , set a 93 and set b 47-----------------i am thread 6 get rawa 93 and get rawb 47 , set a 56 and set b 90-----------------i am thread 4 get rawa 56 and get rawb 90 , set a 81 and set b 35-----------------i am thread 5 get rawa 81 and get rawb 35 , set a 74 and set b 20-----------------i am thread 9 get rawa 74 and get rawb 20 , set a 65 and set b 0-----------------i am thread 2 get rawa 65 and get rawb 0 , set a 56 and set b 62-----------------i am thread 0 get rawa 56 and get rawb 62 , set a 70 and set b 45-----------------i am thread 1 get rawa 70 and get rawb 45 , set a 39 and set b 62-----------------i am thread 3 get rawa 39 and get rawb 62 , set a 34 and set b 90-----------------i am thread 8 get rawa 34 and get rawb 90 , set a 33 and set b 57-----------------i am thread 7 get rawa 33 and get rawb 57 , set a 47 and set b 6-----------------i am thread 6 get rawa 47 and get rawb 6 , set a 6 and set b 1-----------------i am thread 4 get rawa 6 and get rawb 1 , set a 22 and set b 8-----------------i am thread 5 get rawa 22 and get rawb 8 , set a 65 and set b 72-----------------i am thread 9 get rawa 65 and get rawb 72 , set a 54 and set b 96-----------------i am thread 2 get rawa 54 and get rawb 96 , set a 79 and set b 59-----------------i am thread 0 get rawa 79 and get rawb 59 , set a 19 and set b 48-----------------i am thread 1 get rawa 19 and get rawb 48 , set a 99 and set b 12-----------------i am thread 3 get rawa 99 and get rawb 12 , set a 9 and set b 69-----------------i am thread 8 get rawa 9 and get rawb 69 , set a 97 and set b 16-----------------i am thread 7 get rawa 97 and get rawb 16 , set a 79 and set b 46-----------------i am thread 4 get rawa 73 and get rawb 95 , set a 45 and set b 7-----------------i am thread 5 get rawa 45 and get rawb 7 , set a 71 and set b 66-----------------
阅读全文
0 0
- 设计模式之 单例设计模式
- 设计模式之 单例设计模式
- 设计模式之单例设计模式
- 设计模式之-----------单例设计模式
- 设计模式之:单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之-单例设计模式
- 设计模式之单例设计模式 标签: 设计模式
- 设计模式之单例
- 设计模式之单例
- 设计模式之 单例
- ssh 免密码设置失败原因总结
- 搭建并多端口共享ipv4&ipv6ss服务端,实现校园网免流量
- SCUT Training 20170913 Problem K
- Springmvc拦截器简单使用以及session超时跳转
- 鸡肋代码
- 设计模式之:单例模式
- Git
- 企业如何预防「意外掉电」带来的数据安全威胁?
- c/c++中#include <>与#include""区别
- OnSize、OnSizing和OnGetMinMaxInfo区别分析
- hive 函数
- [C#] Direct2D 学习笔记 (一)vb.net转换为c#
- iOS 图片压缩----微信图片处理策略
- rem布局,移动H5页面布局规范(1)。