单例创建两种方式
来源:互联网 发布:excel两张表数据匹配 编辑:程序博客网 时间:2024/06/04 20:01
创建单例
有两种方法来创建单例,下面分别介绍
1、GCD方式创建单例
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [
super
allocWithZone:zone];
});
return
_instance;
}
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
return
_instance;
}
- (id)copyWithZone:(NSZone *)zone
{
return
_instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return
_instance;
}
2、互斥锁方式
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
@synchronized(self) {
if
(_instance == nil) {
_instance = [
super
allocWithZone:zone];
}
}
return
_instance;
}
+ (instancetype)sharedInstance
{
@synchronized(self) {
if
(_instance == nil) {
_instance = [[self alloc] init];
}
}
return
_instance;
}
- (id)copyWithZone:(NSZone *)zone
{
return
_instance;
}
上面两种方式都可以创建单例,而且保证了用户不管是通过shareInstance方法,还是alloc、copy方法得到的实例都是一样的。
上面代码的关键之处就在于如何在多线程情况下保证创建的单例还是同一个。
我们先看看在GCD情况下,如果不使用dispatch_once和同步锁创建单例会出现什么问题,去掉两者后创建单例的代码如下
+ (instancetype)sharedInstance
{
if
(_instance == nil) {
_instance = [[self alloc] init];
}
}
假设此时有两条线程:线程1和线程2,都在调用shareInstance方法来创建单例,那么线程1运行到if (_instance == nil)出发现_instance = nil,那么就会初始化一个_instance,假设此时线程2也运行到if的判断处了,此时线程1还没有创建完成实例_instance,所以此时_instance = nil还是成立的,那么线程2又会创建一个_instace。
此时就创建了两个实例对象,导致问题。
解决办法1、使用dispatch_once
dispatch_once保证程序在运行过程中只会被运行一次,那么假设此时线程1先执行shareInstance方法,创建了一个实例对象,线程2就不会再去执行dispatch_once的代码了。从而保证了只会创建一个实例对象。
解决办法2、使用互斥锁
假设此时线程1在执行shareInstance方法,那么synchronize大括号内创建单例的代码,如下所示:
if
(_instance == nil) {
_instance = [[self alloc] init];
}
就会被当做一个任务被加上了一把锁。此时假设线程2也想执行shareInstance方法创建单例,但是看到了线程1加的互斥锁,就会进入睡眠模式。等到线程1执行完毕,才会被唤醒,然后去执行上面所示的创建单例的代码,但是此时_instance !=nil,所以不会再创建新的实例对象了。从而保证只会创建一个实例对象。
但是互斥锁会影响性能,所以最好还是使用GCD方式创建单例。
- 创建单例的两种方式
- 单例的两种创建方式
- 单例的两种创建方式
- 单例创建两种方式
- iOS两种创建单例的方式
- iOS中创建单例的两种方式
- 创建单例的两种方式(懒汉式&GCD)
- 两种创建单例模式的方式-懒汉式与饿汉式
- GCD常用基本API介绍以及创建单例的两种方式
- 单例模式的两种方式
- 单例模式的两种方式
- 单例模式的两种方式
- <单例模式的两种方式>
- 单例模式两种实现方式
- 单例的两种实现方式
- 单例的两种创建方法
- 两种方法创建单例
- 五种创建单例的方式
- 测试 PIC16F877A 《==》 MAX6902
- 如何制作弹出窗口
- Lua入门教程 6.迭代器与泛型for
- 多线程实现的两种方式
- Spring基础
- 单例创建两种方式
- 学习笔记之atexit()函数
- Flex 布局教程:语法篇
- JDK安装与环境变量配置
- HDOJ 5265 pog loves szh II
- MAC 系统 PHP配置和Apache配置
- oracle数据库的数据查询语言DQl
- Flex 布局教程:实例篇
- form属性method="get/post"的两种方式对比