设计模式:单例模式(singleton)
2024-08-28 20:25:24
singleton模式属于创建型设计模式。其作用是在程序设计中,对于某一个类而言,全局只能存在一个实例对象。
下面以C++为例,对单例模式进行说明:
1. 最基本单例模式(单线程)
class Singleton1{
private:
static Singleton1 instance;
Singleton1(){} //构造函数
public:
static Singleton1 get_instance(){
if (Singleton1.instance==nullptr){ //若当前唯一实例为空,则创建新对象返回
instance=Singleton1();
}
return instance;
}
};
存在问题:在单线程下,只有instance == null 时,才会创建新对象,其余时间返回。但是对于多线程访问时,当两个或多个线程同时访问到instance==null,若判断成立,多个线程会分别实例化对象,这时程序就不满足单例条件了。
2.多线程的单例模式
针对上述问题,要在多线程中保证单例,就要进行线程同步控制,C++中使用mutex类族进行同步控制。
class Singleton2{
private:
static Singleton2 instance;
static std::mutex mutex_var;
Singleton2(){}
public:
static Singleton2 get_instance(){
mutex_var.lock(); //互斥量加锁进行线程同步
if (instance==nullptr){
instance=Singleton2();
}
mutex_var.unlock(); //互斥量解锁
return instance;
}
};
存在问题:线程安全,但程序效率不高。注意,此前讨论的出现的不满足单例的情况只出现在首次实例化对象时,但现在的程序在每次通过ger_instance函数访问时,都会进行加解锁操作,,加锁操作是十分耗时的,从而导致程序效率变低。
3.多线程下高效的单例模式
解决方法:仅在第一次实例化的时候加锁,其他时刻不加锁,提高程序效率。
class Singleton3{
private:
static Singleton3 instance;
static std::mutex mutex_var;
Singleton3(){}
public:
static Singleton3 get_instance(){
if (instance==nullptr) //外层多一次判断,如果单例已经存在,就不再进行加锁操作
{
mutex_var.lock(); //互斥量加锁进行线程同步
if (instance==nullptr){
instance=Singleton3();
}
mutex_var.unlock(); //互斥量解锁
}
return instance;
}
};
关于懒汉式和饿汉式的讨论
饿汉式:单例实例在类装载时就构建,急切初始化。(预先加载法)
懒汉式:单例实例在第一次被使用时构建,延迟初始化。(上述实现都是懒汉式的)。
这两类单例模式的区别在于实例化的时机不同。
饿汉式
优点:线程安全,在类加载的同时创建一个静态对象,调用时反应快。缺点:由于是提前定义,可能在全局程序中都没有使用这个实例,资源利用率不高。
懒汉式
优点:资源效率高,只要不用到该实例就不会被实例化。缺点:第一次加载速度不快。
两种方式各有优劣,针对不同的场景进行选择,一般情况下,使用饿汉式更多一些。
最新文章
- 微信小程序二维码推广统计
- HDU-2296 Ring(AC自动机+DP)
- DIOCP单元文件应用场景
- Ext-ajax请求数据
- mac上安装homebrew
- VS中引用第三方库的方法(配置sqlite数据库)
- python中将字符串转化为本地变量
- iOS App集成Apple Pay教程(附示例代码)
- node.js学习系列(一)
- IO (三)
- idea 配置git
- ORM 多表操作查询及增删改查
- 再议mysql 主从配置
- CAAnimation临时取消动画,永久取消动画
- sql语句执行出错:Incorrect integer value: '' for column 'id' at row 1
- oc的静态函数static
- IOS上z-index和fixed定位无效
- Windows改桌面文件路径
- SpringInAction--SpringMvc高级技术(servlet、filter、multipart)
- aspnetcore 认证相关类简要说明一
热门文章
- WebSocket实现Java后台消息推送
- [20190918]关于函数索引问题.txt
- 获取BOM标准用量
- [Go] 使用go mod安装beego
- Java重定向标准输入/输出
- 8.Python网络编程_多线程死锁
- 201871010111-刘佳华《面向对象程序设计(java)》第十一周学习总结
- luoguP2178 [NOI2015]品酒大会(后缀数组做法)
- [LeetCode] 238. Product of Array Except Self 除本身之外的数组之积
- win10挂载efi分区