OC基础-单例的实现 & 提醒自己注意多线程问题

栏目: IOS · 发布时间: 7年前

内容简介:做客户端开发应当时刻考虑多线程问题。我最初是做前端开发的,在这方面考虑得往往不够。谨记。单例的常见写法其实就两种dispatch_once的写法更推荐一些。一方面是性能上好一点,另一方面是语义上更直观。once,执行一次嘛。

做客户端开发应当时刻考虑多线程问题。我最初是做前端开发的,在这方面考虑得往往不够。谨记。

单例的常见写法

单例的常见写法其实就两种

1. 依赖锁

+ (id)sharedInstance {  
    static testClass *sharedInstance = nil;  
    @synchronized(self) {  
        if (!sharedInstance) {  
            sharedInstance = [[self alloc] init];  
        }  
    }  
    return sharedInstance;  
}

2. 依赖dispatch_once

+ (id)sharedInstance {  
    static testClass *sharedInstance = nil;  
    static dispatch_once_t once;  
    dispatch_once(&once, ^{  
        sharedInstance = [[self alloc] init];  
    });  
    return sharedInstance;  
}

dispatch_once的写法更推荐一些。一方面是性能上好一点,另一方面是语义上更直观。once,执行一次嘛。

不管是用锁还是dispatch_once,本质上都是为了避免单例创建过程出现线程安全问题。

更进一步,我们经常会有懒加载某些属性的写法:

- (id<InterfaceEngineA>)engineA
{
    if (_engineA == nil) {
        _engineA = [EngineA new];
    }
    
    return _engineA;
}

其实跟单例的实现是类似的,这种时候要格外注意线程安全问题。如果存在多线程场景,一定要做好保护

- (id<InterfaceEngineA>)engineA
{
    @synchronized(self) {
        if (_engineA == nil) {
            _engineA = [EngineA new];
        }
    }
    return _engineA;
}

一些废话

多线程问题的表现可能是各种各样难以预料的。这里我遇到的是,_engineA在多线程场景下小概率被重复创建,其实例1在init时注册了网络层命令字 cmd1 的回包,而这个网络层框架的实现是,只接受第一个注册这一命令字的对象。导致实例2注册失败。后面调用实例2发送请求,回包都被实例1接收了。从日志上看,一切都挺正常的。但是下次取数据就是取不到。

这个bug第一次提过来的时候,没分析出根本原因,只在表面上做了保护。结果第二次提过来才真正改掉。

丢人呐。还是要好好学习才是。


以上所述就是小编给大家介绍的《OC基础-单例的实现 & 提醒自己注意多线程问题》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

面向对象技术UML教程

面向对象技术UML教程

王少峰 / 清华大学出版社 / 2004-2 / 24.00元

《面向对象技术UML教程》主要介绍统一建模语言UML及其应用。全书内容丰富,包括UML的用例图、顺序图、协作图、类图、对象图、状态图、活动图、构件图和部署图等9个图中所涉及的术语、规则和应用,以及数据建模、OCL、业务建模、Web建模、设计模式、OO实现语言、RUP等方面的内容,同时介绍了Rose开发工具中的一些用法。《面向对象技术UML教程》最后是一个课程注册系统的实例研究,以及一些思考题和设计......一起来看看 《面向对象技术UML教程》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试