GCD之用dispatch_once创建单例
2016-06-01 00:00
183 查看
摘要: 使用dispatch_once 来执行只需运行一次的线程安全代码
单例模式是开发者常用的一种设置模式,常见的实现方式为:在类中编写名为 sharedInstance的方法,该方法只会返回全类共用的单例实例,而不会在每次调用时创建新的实例.
常见的做法是:
为了保证线程安全,上面的代码把创建代理的代码包裹在同步块里.
相对于上面的实现方式,使用GCD的dispatch_once实现起来更为容易. 所用到的函数是:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// code to be executed once
});
此函数接受的类型为 dispatch_once_t的特殊函数 token,此外还接受块参数.对于给定的token来说,该函数保证相关的块必定会执行,且仅执行一次.首次调用该函数时必然会执行块中的代码,最重要的是:次操作完全是线程安全的!!!需要注意的是:对于只需执行一次的块来说,每次调用函数时传入的token必须完全相同.所以通常将token标记声明在static或者global作用域里.
使用GCD实现单例方法如下:
使用dispatch_once可以简化代码并且实现线程安全,因此你无需担心加锁或者同步的问题.所有问题都有GCD在底层处理.由于每次调用时都必须使用完全相同的token,所以token需要声明为static. 把token声明在static作用内,可以保证编译器每次执行shareUser方法时都会复用这个变量,而不会创建新的变量.
此外,dispatch_once更高效. 他没有使用重量级的加锁机制,如果是使用加锁的话,每次运行代码前都要获取锁,相反 dispatch_once 函数采用原子访问来查询token,以判断对应的代码是否已经执行过.
--> 使用 dispathch_once 可以轻松编写 "只需运行一次的线程安全代码",可以轻松实现单例.
--> token 应该声明在static或者golbal作用域中,这样的话吧只需执行一次的块传给dispatch_once函数时,可以保证传进去的token也是相同的.
附赠一份快速实现单例的 .h 文件
调用如下:
1.导入 Singleton.h文件
2.在类的.h文件中 singleton_h(单例的名字),以User类举例,单例的名字会自动拼接上 shared
3.调用
User *user = [User sharedUser];
------------------
文献参考:<编写高质量OSX和iOS代码的52个有效方法>
单例模式是开发者常用的一种设置模式,常见的实现方式为:在类中编写名为 sharedInstance的方法,该方法只会返回全类共用的单例实例,而不会在每次调用时创建新的实例.
常见的做法是:
+ (instancetype)sharedUser { static User *_sharedInstance = nil; @synchronized(self) { if (!_sharedInstance) { _sharedInstance = [[self alloc] init]; } } return _sharedInstance; }
为了保证线程安全,上面的代码把创建代理的代码包裹在同步块里.
相对于上面的实现方式,使用GCD的dispatch_once实现起来更为容易. 所用到的函数是:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// code to be executed once
});
此函数接受的类型为 dispatch_once_t的特殊函数 token,此外还接受块参数.对于给定的token来说,该函数保证相关的块必定会执行,且仅执行一次.首次调用该函数时必然会执行块中的代码,最重要的是:次操作完全是线程安全的!!!需要注意的是:对于只需执行一次的块来说,每次调用函数时传入的token必须完全相同.所以通常将token标记声明在static或者global作用域里.
使用GCD实现单例方法如下:
+ (instancetype)sharedUser{ static User *_shareInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (!_shareInstance) { _shareInstance = [[self alloc] init]; } }); return _shareInstance; }
使用dispatch_once可以简化代码并且实现线程安全,因此你无需担心加锁或者同步的问题.所有问题都有GCD在底层处理.由于每次调用时都必须使用完全相同的token,所以token需要声明为static. 把token声明在static作用内,可以保证编译器每次执行shareUser方法时都会复用这个变量,而不会创建新的变量.
此外,dispatch_once更高效. 他没有使用重量级的加锁机制,如果是使用加锁的话,每次运行代码前都要获取锁,相反 dispatch_once 函数采用原子访问来查询token,以判断对应的代码是否已经执行过.
--> 使用 dispathch_once 可以轻松编写 "只需运行一次的线程安全代码",可以轻松实现单例.
--> token 应该声明在static或者golbal作用域中,这样的话吧只需执行一次的块传给dispatch_once函数时,可以保证传进去的token也是相同的.
附赠一份快速实现单例的 .h 文件
调用如下:
1.导入 Singleton.h文件
2.在类的.h文件中 singleton_h(单例的名字),以User类举例,单例的名字会自动拼接上 shared
#import <Foundation/Foundation.h> #import "Singleton.h" @interface User : NSObject singleton_h(User); @end #import "User.h" @implementation User singleton_m(User); @end
3.调用
User *user = [User sharedUser];
// ## : 连接字符串和参数 #define singleton_h(name) + (instancetype)shared##name; #if __has_feature(objc_arc) // ARC #define singleton_m(name) \ static id _instance; \ + (id)allocWithZone:(struct _NSZone *)zone \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instance = [super allocWithZone:zone]; \ }); \ return _instance; \ } \ \ + (instancetype)shared##name \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instance = [[self alloc] init]; \ });\ return _instance; \ } \ + (id)copyWithZone:(struct _NSZone *)zone \ { \ return _instance; \ } #else // 非ARC #define singleton_m(name) \ static id _instance; \ + (id)allocWithZone:(struct _NSZone *)zone \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instance = [super allocWithZone:zone]; \ }); \ return _instance; \ } \ \ + (instancetype)shared##name \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instance = [[self alloc] init]; \ }); \ return _instance; \ } \ \ - (oneway void)release \ { \ \ } \ \ - (id)autorelease \ { \ return _instance; \ } \ \ - (id)retain \ { \ return _instance; \ } \ \ - (NSUInteger)retainCount \ { \ return 1; \ } \ \ + (id)copyWithZone:(struct _NSZone *)zone \ { \ return _instance; \ } #endif
------------------
文献参考:<编写高质量OSX和iOS代码的52个有效方法>
相关文章推荐
- 设计模式之创建型模式 - 特别的变量问题
- C#单例模式(Singleton Pattern)实例教程
- 举例讲解C#编程中对设计模式中的单例模式的运用
- php设计模式之单例模式实例分析
- PHP基于单例模式实现的数据库操作基类
- JavaScript编程的单例设计模讲解
- C#设计模式之单例模式实例讲解
- Javascript实现单例模式
- JS模式之单例模式基本用法
- 深入理解JavaScript系列(25):设计模式之单例模式详解
- 使用设计模式中的单例模式来实现C++的boost库
- php设计模式之单例、多例设计模式的应用分析
- javascript 单例/单体模式(Singleton)
- Java单例模式、饥饿模式代码实例
- java设计优化之单例模式
- Android源码学习之单例模式应用及优点介绍
- JavaScript实现设计模式中的单例模式的一些技巧总结
- C++设计模式之单例模式
- C#窗口实现单例模式的方法
- Java线程安全中的单例模式