单例模式的意义
保证全局只会创建一个对象,比如 日志模块全局只有一个,windows的任务管理器等,这样可以避免频繁的创建销毁对象,还可以避免对共享资源的多重占用,具体例子和好处坏处看参考资料[9],不赘述
几个要考虑的问题:
- 懒加载;;
- 线程安全生存周期的考虑;;
- 反序列化;;
- 反射单例;;
- 克隆单例
实现思想
首先是一个唯一性,保证全部成员只能访问到一个共同的对象
为了防止对象被创建多次,要把构造函数设为private,以防止被他人调用重复建立,而自己单独实现一个接口用来获取实例(可以把构造函数当作这个接口吗?),并且要把赋值函数operator=删去,拷贝构造函数会导致创建新对象也要删掉,
自己实现的接口中,防止对象地址暴露被用户delete,返回类型不能为指针,又因为删掉了拷贝构造,所以只能返回引用所以要注意get()不能返回指针类型,
不太行的方案
- 如果把数据用static包装,即 static singleton data,可以实现单例模式,但是缺点是在程序开始的时候初始化启动比较慢,如果没用到这个单例模式还是会占用一定的空间
- 如果把数据用指针存储,在getdata的时候创建,需要加锁来保证线程安全,一种方式是DCL,但是C++里volitile不像java,防止不了指令重排(如指令重排、多核处理器等问题让DCLP实现起来比较复杂),这里不赘述,见参考资料
- DCL在C++里可以利用barrier来实现,能防止指令重排,陈硕说这个用这个杀鸡用牛刀(可能开销太大吧)
std::atomic<Singleton*> m_instance;
Singleton* Singleton::getInstance() {
Singleton* tmp = m_instance.load(std::memory_order_relaxed);
// 屏蔽reorder
std::atomic_thread_fence(std::memory_order_acquire); // 获取内存fence
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(m_mutex);
tmp = m_instance.load(std::memory_order_relaxed);
if (tmp = nullptr) {
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_release);// 释放内存fence
m_instance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
可行的方案
局部静态类(Meyers Singleton)
懒加载不会有上面直接用static成员的缺点,且没有线程安全问题(C++0x之后是该实现线程安全的),大概代码如下
class singleton
{
singleton &getdata(){
static singleton data;
return data;
}
}
pthread_once
在muduo中就采用了pthread_once来实现单例,这个API很简单,可以看一下https://blog.csdn.net/ericbar/article/details/79879850
更高级的方案
[求教一个百度的面试题,关于多线程单例模式的? - 知乎 https://www.zhihu.com/question/27704562]
上面这个链接里面也提到了其他的高级一点的实现方法,也有上面提到的几种
参考资料
- https://www.cnblogs.com/loveis715/archive/2012/07/18/2598409.html很不错,讲了cpp的,考虑了重用和线程安全,以上全部可以看这个
- https://zhuanlan.zhihu.com/p/176706256这里说了Meyers和泄露单例,不懂啊
- https://mp.weixin.qq.com/s?__biz=MzAwNDcyODk5NQ==&mid=2647599434&idx=1&sn=bad8164bbb3b38d31500e60f1b3aec76单例模式java的十种写法,好像没用上
- https://zhuanlan.zhihu.com/p/105586046几种实现模式,提到了序列化和枚举是啥啊
- https://zhuanlan.zhihu.com/p/160842212评论说其实用枚举和静态内部类都是很好的选择,因为可以防序列化问题。
- https://blog.csdn.net/wansbest/article/details/8664764这cpp的单例写法,看不懂啊
- https://www.cnblogs.com/qicosmos/p/3145019.html这个cpp11改进的单例,用了模板可以通用
- https://blog.csdn.net/zztan/article/details/54691809cpp的实现,给了个回收资源的写法
- https://www.cnblogs.com/cthon/p/9196664.html讲了cpp的实现,,全部都讲了,混着java的,内部静态类.还讲了pthread_once
- https://www.bilibili.com/video/BV1Gz4y1d7RJ讲cpp的单例
- https://blog.csdn.net/liqingbing12/article/details/107494972很全的cpp单例
- https://www.jianshu.com/p/76718311fbb0这个cpp单例,文中pthread_once和Meyers singleton来源
- https://blog.csdn.net/u011726005/article/details/82356538也挺全,参考了评论的DCL防指令重排
本文探讨了C++中的单例模式,包括其意义、考虑的问题和多种实现方案。重点介绍了局部静态类(Meyers Singleton)和pthread_once方法,并提到了线程安全和防止多次实例化的策略。同时,文章提供了多个参考资料,详细讲解了不同场景下的单例模式实现。

3867

被折叠的 条评论
为什么被折叠?



