iOS 浅谈各种同步机制

什么时候需要用到同步

在同一块内存,可能会被多个线程并发访问的情况下,一般考虑数据同步

同步机制分为3种

根据不同的同步机制,大致可以分3种,分别是:

1、锁:阻塞当前线程,等待一定条件,再往下走
2、串行队列:通过队列,把不同的数据操作代码,放在同一个线程执行
3、信号量:控制线程挂起/唤醒

下面分别来说说它们各自的工作原理。

以自旋锁为例:


线程1走在lock与unlock之间时,
线程2走到lock时,会执行原地进行循环,转圈,并阻止代码往下走。

这样,线程2和1不会同时访问到同一片资源。等线程1访问完了,线程2就会跳出循环,再进行数据操作。

串行队列

不同的线程,把各自数据操作任务,都放入队列中。然后,队列依次把任务取出来,放到同一条线程中执行,实现同步

信号量

原理跟自旋类似。只不过是从循环变成线程挂起。
如果把它们两个比喻成过红绿灯的车子,自旋就是红灯时原地打圈,信号量就是红灯停车,等绿灯再通过。

两者相比,
自旋:一个不停运行的循环,消耗cpu计算资源,不需要唤醒,响应快
信号量:挂起与唤醒有时间开销,响应稍慢,但挂起节省cpu

iOS中的同步

  • 上锁
    简单的有NSLock,@synchronized()

  • 使用串行队列
    dispatch_queue,dispatch代码块到同一个串行queue

  • 使用信号量
    dispatch_semaphore,通过wait与signal控制
    或者dispatch_group,同理。

最后说两句

一般的业务场景,客户端没有什么大并发,通常瓶颈不在于用什么锁,@synchronized()充以满足业务需求。

只有一点值得注意的是,@synchronized(一块地址),一地址对应一个锁。
常说@synchronized()性能差,很多时候是使用不规范。滥用@synchronized(self),相当于所有业务都使用的同一个锁。这意味着在有些时候业务A的进度,需要等待不相关的业务B,能不卡么。

正确的使用姿势是:合理地使用@synchronized( lock_obj1 / lock_obj2 ... ),不同业务使用不同的LockObject。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

推荐阅读更多精彩内容