阅读 315

iOS 常见锁的简单认识

iOS中常见的锁有哪些?

@synchronized,信号量dispatch_semaphore_tos_unfair_lock,实现了NSLocking的几个类(NSLockNSRecursiveLockNSConditionNSConditionLock

上面提到的都是互斥锁(即线程在尝试访问共享资源的时候,发现有锁,就休眠进行等待唤醒)。

关于锁的性能

网上有很多讨论锁性能的文章,但是我觉得这个大可不必。

首先肯定是功能简单,越贴近底层的锁性能最高。

比如实现了递归功能的锁性能一定是比不实现递归的锁要性能高。

但是抛开功能来谈性能,这不是有点无聊吗?

其次,网上的demo里都是在一个for循环里面,先加锁再解锁,没有考虑到多线程的情况。

我也不知道这样得出来的性能对比是否有意义。

拿了网上的demo,跑了一下。

循环在1万次的时候,可以看到各个锁的性能差别不大。最好的与最坏的差了三百多毫秒

因此我觉得在日常开发过程中,其实可以不考虑锁的性能,把精力放到功能实现上即可。

截屏2021-10-18 下午2.49.25.png

锁的一些简单介绍

@synchronized

使用代码一般如下:

@synchronized** ( self ) {
   // do something
}复制代码

功能非常强大。可以在多线程中保证数据安全,同时也支持递归使用。

内部的实现流程大致是(不考虑缓存的情况):

  • 加锁之前,先从线程的TLS存储空间中尝试获取数据data

  • 如果数据data存在,并且锁标识和当前传入的锁标识一样,那么就说明当前线程已经有锁,这个时候将lockcount计数加1,然后结束流程,进行mutex加锁操作。

  • 走到这里,说明没有data或者锁标识不一致。

  • 没有data的情况,直接创建data,并将threadcount计数加1,结束流程,进行mutex加锁操作。

  • 如果有data,只是锁的标识不一致,那就创建新的data,将其插入到链表的头部,结束流程,进行mutex加锁操作。

NSLock

是一个相对来说比较简单的互斥锁。

使用的时候需要注意:

  • 不支持递归,即同一条线程不能在未解锁之前进行加锁操作。

  • 加锁和解锁的操作必须在同一条线程进行

NSRecursiveLock/ pthread_mutex(recursive)

可以实现递归加锁功能。

NSCondition / NSConditionLock

在锁的基础上可以追加一些条件。

NSCondition的使用如下:截屏2021-10-18 下午3.47.43.png

NSConditionLock使用如下:截屏2021-10-18 下午4.13.46.png可以看到,当condition不满足的时候,当前执行线程会被卡住,直到条件满足后继续执行。

dispatch_semaphore

利用dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);dispatch_semaphore_signal(dispatch_semaphore_t dsema);来实现锁的效果。

dispatch_semaphore_wait会将信号量减去1,如果此时信号量值小于0,就会卡住线程,等待唤醒dispatch_semaphore_signal会将信号量加1,如果之前的信号量小于0,就会唤醒之前等待的线程。

os_unfair_lock

用来替代OSSpinLock,因为OSSpinLock存在优先级反转的问题,已经被弃用了。

OSSpinLock弃用原因:

高优先级线程始终在低优先级线程前执行。如果一个低优先级的线程先获得了锁并访问共享资源, 这个时候高优先级线程也尝试获得锁,就会出现高优先级线程在等待锁, 而低优先级线程在等高优先级线程用完CPU

值得注意的是os_unfair_lock是互斥锁,OSSpinLock是自旋锁。

读写锁

很早之前记得有个面试题,面试官让我实现:

  • 同一时间,只能有一个线程进行setter操作;

  • 同一时间,允许多个线程进行getter操作;

  • 同一时间,setter和getter操作互斥;

前不久看一个视频才明白这是一个读写锁的实际场景。

解决方案是利用栅栏函数

截屏2021-10-18 下午9.33.16.png


作者:雨天多久就
链接:https://juejin.cn/post/7020399656861433870


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐