博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ObjC 多线程简析(二)- os_unfair_lock的类型和自旋锁与互斥锁的比较
阅读量:7072 次
发布时间:2019-06-28

本文共 1967 字,大约阅读时间需要 6 分钟。

在iOS10之后apple废弃了OSSpinLock自旋锁,使用os_unfair_lock来替代。

OSSpinLock的api注释中明确指出这是一个自旋锁,那么它的替代方案是一把什么类型的锁呢?

我们知道自旋锁加锁的时候,等待锁的线程处于忙等状态,并且占用着CPU的资源。而互斥锁加锁的时候,等待锁的线程处于休眠状态,不会占用CPU的资源。

那么我们探就加锁状态下的等待锁的线程的状态就可以得出os_unfair_lock这把锁的类型。

探究os_unfair_lock的类型

依然使用卖票的经典案例,分别使用OSSpinLockos_unfair_lock加锁,当第二条线程执行到加锁代码的时候,是处于等待锁的状态,这个时候我们通过汇编代码窥探等待锁的线程的状态,得出其是自旋锁还是互斥锁。

依然使用中提到的卖票的案例。

#import "ViewController.h"@interface ViewController ()@property (nonatomic, assign) int ticketCount;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    // 初始化锁    // ...    [self ticket];}- (void)saleTicket {    // 加锁    // ...    int oldTicketCount = _ticketCount;    sleep(1); //让线程睡眠1秒 更能体现多线程的隐患    oldTicketCount --;    _ticketCount = oldTicketCount;    NSLog(@"剩余的票数%d",_ticketCount);    // 解锁    // ...}- (void)ticket {    self.ticketCount = 20;    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);    dispatch_async(queue, ^{        for (int i = 0; i < 5; i++) {            [self saleTicket];        }    });    dispatch_async(queue, ^{        for (int i = 0; i < 5; i++) {            [self saleTicket];        }    });    dispatch_async(queue, ^{        for (int i = 0; i < 5; i++) {            [self saleTicket];        }    });    dispatch_async(queue, ^{        for (int i = 0; i < 5; i++) {            [self saleTicket];        }    });}复制代码

在Xcode中对加锁代码进行断点,然后点击任务栏Debug->Debug Worlflow->Always Show Disassembly。在xcode的lldb下使用si命令让汇编代码一步一步的执行,观察等待锁的线程状态:

我们发现线程进入了上述的状态,这期是相当于一个while循环。这个循环等到自旋锁解锁之后进入下面的代码继续执行。这就是自旋锁忙等的状态。

下面我们来看使用os_unfair_lock的情况,使用它在代码注释的地方进行初始化,并且进行加锁和解锁,重复上述操作进行观察。

当汇编代码执行到这一行的时候不再继续往下执行,断点也失去了作用。这是因为syscall调用了系统内核的函数,使得线程进入休眠状态,不再占用CPU资源。所以根据上面描述的自旋锁和互斥锁的区别os_unfair_lock属于互斥锁。

自旋锁和互斥锁的比较

当预计线程等待锁的时间很短,或者加锁的代码(临界区)经常被调用,但竞争情况很少发生,再或者CPU资源不紧张,拥有多核处理器的时候使用自旋锁比较合适。

而当预计线程等待锁的时间较长,CPU是单核处理器,或者临界区有IO操作,或者临界区代码复杂或者循环量大,临界区竞争非常激烈的时候使用互斥锁比较合适

总结

在iOS10之后apple已经不再建议使用OSSpinLock自旋锁了,它的替代方案是一个互斥锁,所以一般情况下我们使用互斥锁来解决线程同步的问题才是比较合理的。

转载地址:http://qehll.baihongyu.com/

你可能感兴趣的文章
spring容器启动的三种方式
查看>>
第七届河南省赛A.物资调度(dfs)
查看>>
iOS开发-获取设备型号信息
查看>>
ASP.NET MVC Html.BeginForm 设置 timeout
查看>>
全文检索引擎Solr系列——整合MySQL、MongoDB
查看>>
瑞丽的SQL-SQL Server的表旋转(行列转换)
查看>>
Storm技术结合
查看>>
LintCode 二叉树的层次遍历 II
查看>>
4.Java 加解密技术系列之 HMAC
查看>>
SQL server语句练习
查看>>
Scala 基础入门【翻译】
查看>>
Android.mk具体解释
查看>>
宝宝去了幼儿园不爱说话怎么办?
查看>>
nginx 301跳转到带www域名方法rewrite(转)
查看>>
Enterprise Architect与startUML表示UML常用图
查看>>
飘逸的python - 使用dis模块进行代码层次的性能剖析
查看>>
Web jquery表格组件 JQGrid 的使用 - 8.Pager、新增数据、查询、刷新、查看数据
查看>>
在Linux上以服务的方式运行ASP.NET Core站点
查看>>
Java 文件名操作的相关工具类
查看>>
Java多线程-线程的调度(合并)
查看>>