单例模式算是开发中比较常见的一种模式了。在iOS中,单例有两种实现方式(至少我目前只发现两种)。根据线程安全的实现来区分,一种是使用@synchronized,另一种是使用GCD的dispatch_once函数。

要实现单例,首先需要一个static的指向类本身的对象,其次需要一个初始化类函数。下面是两种实现的代码。

1、@synchronized

static InstanceClass *instance;
+ (InstanceClass *)defaultInstance{
@synchronized (self){
if (instance == nil) {
instance = [[InstanceClass alloc] init];
}
} return instance;
}

2、GCD

static InstanceClass *instance;
+ (InstanceClass *)defaultInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[InstanceClass alloc] init];
}); return instance;
}

总的来说,两种实现效果相同,但第二种GCD的实现方式写起来比较简单。如果不习惯GCD的方式,可以使用第一种方式。

两种单利模式的优劣:

单次初始化

GCD还提供单词初始化支持,这个与pthread中的函数  pthread_once 很相似。GCD提供的方式的优点在于它使用block而非函数指针,这就允许更自然的代码方式:

这个特性的主要用途是惰性单例初始化或者其他的线程安全数据共享。典型的单例初始化技术看起来像这样(线程安全的):

    + (id)sharedWhatever
{
static Whatever *whatever = nil;
@synchronized([Whatever class])
{
if(!whatever)
whatever = [[Whatever alloc] init];
}
return whatever;
}

这挺好的,但是代价比较昂贵;每次调用  +sharedWhatever 函数都会付出取锁的代价,即使这个锁只需要进行一次。确实有更风骚的方式来实现这个,使用类似双向锁或者是原子操作的东西,但是这样挺难弄而且容易出错。

使用GCD,我们可以这样重写上面的方法,使用函数 dispatch_once

    + (id)sharedWhatever
{
static dispatch_once_t pred;
static Whatever *whatever = nil;
dispatch_once(&pred, ^{
whatever = [[Whatever alloc] init];
});
return whatever;
}

这个稍微比 @synchronized方法简单些,并且GCD确保以更快的方式完成这些检测,它保证block中的代码在任何线程通过  dispatch_once 调用之前被执行,但它不会强制每次调用这个函数都让代码进行同步控制。实际上,如果你去看这个函数所在的头文件,你会发现目前它的实现其实是一个宏,进行了内联的初始化测试,这意味着通常情况下,你不用付出函数调用的负载代价,并且会有更少的同步控制负载。

iOS单例的两种实现的更多相关文章

  1. objc单例的两种安全实现方案

    所有转出博客园,请您注明出处:http://www.cnblogs.com/xiaobajiu/p/4122034.html objc的单例的两种安全实现方案 首先应该知道单例的实现有两大类,一个是懒 ...

  2. iOS 创建单例的两种方法

    创建一个单例很多办法.我先列举一个苹果官方文档中的写法. [cpp] view plaincopy static AccountManager *DefaultManager = nil; + (Ac ...

  3. 【iOS开发】创建单例的两种方法

    创建一个单例很多办法.我先列举一个苹果官方文档中的写法. [cpp] view plaincopy   static AccountManager *DefaultManager = nil; + ( ...

  4. IOS创建单例的两种方法

    1.0  苹果官方写法:  static AccountManager *DefaultManager = nil; + (AccountManager *)defaultManager { if ( ...

  5. ios 单例的再次理解

    单例模式    在建模的时候,如果这个东西确实只需要一个对象,多余的对象都是无意义的,那么就考虑用单例模式.比如定位管理(CLLocationManager),硬件设备就只有一  个,弄再多的逻辑对象 ...

  6. 【iOS 单例设计模式】底层解析与运用

    [iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司   单例实例 - 管理 ...

  7. java单例的几种实现方法

    java单例的几种实现方法: 方式1: public class Something { private Something() {} private static class LazyHolder ...

  8. iOS开发笔记-两种单例模式的写法

    iOS开发笔记-两种单例模式的写法   单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" ...

  9. IOS文件操作的两种方式:NSFileManager操作和流操作

    1.常见的NSFileManager文件方法 -(NSData *)contentsAtPath:path //从一个文件读取数据 -(BOOL)createFileAtPath: path cont ...

随机推荐

  1. wcf客户端捕获异常

    直接使用Exception进行捕获,然后在监视器中查看具体是哪一个异常 System.Exception {System.ServiceModel.Security.MessageSecurityEx ...

  2. GPL,LGPL和BSD等协议注意事项

    使用开源软件必须注意GPL,LGPL和BSD等协议 简而言之,GPL协议就是一个开放源代码协议,软件的初始开发者使用了GPL协议并公开软件的源程序后,后续使用该软件源程序开发软件者亦应当根据GPL协议 ...

  3. bzoj1863

    白书上的题目 这里唯一要说一下的就是,二分答案不难想到,怎么构造答案的合理性非常值得注意 ..] of longint;     n,l,r,m,ans,i:longint; function max ...

  4. Apache Hadoop RPC Authentication 安全绕过漏洞

    漏洞名称: Apache Hadoop RPC Authentication 安全绕过漏洞 CNNVD编号: CNNVD-201308-425 发布时间: 2013-08-28 更新时间: 2013- ...

  5. Java Web中web.xml的作用

    每一个javaWeb工程都有一个web.xml配置文件,那么他到底有什么作用呢?它是每一个web工程都必的必须的吗?   web.xml文件是用来初始化工程配置信息的,比如说welcome页面,fil ...

  6. wiki 的捐款呼吁有感而发

    今早在维基百科上查东西时,网页的最上角出现了一栏小广告,我一看居然是维基创始人发的捐款呼吁,点开后网页内容如下: “     来自维基百科创办者Jimmy Wales的个人呼吁 ----------- ...

  7. oracle REPLACE 函数 介绍

    oracle REPLACE 函数是用另外一个值来替代串中的某个值. 例如,可以用一个匹配数字来替代字母的每一次出现.REPLACE 的格式如下所示: REPLACE ( char, search_s ...

  8. LINQ 从 CSV 文件生成 XML

    本文参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx 下面的代码对字符串数组执行 LINQ 查询. 在 C# 版本中,该查询使用 let ...

  9. C#和java和android中的NetWorkAdapter,httpRequest,WebView,json,xml

    原文地址:http://blog.csdn.net/intbird C#NetWorkAdapter 20121011.======================================== ...

  10. DateTime格式大全

    DateTime dt = DateTime.Now;//    Label1.Text = dt.ToString();//2005-11-5 13:21:25//    Label2.Text = ...