iOS中的锁和线程同步
线程同步和iOS中的锁
一、自旋锁(OSSpinLock)
- 一直占用cpu,相当于while循环
- 已经不被推荐,因为可能会产生优先级反转;
优先级反转
- 多任务的调度有许多算法,常见的有FIFO、优先级、时间片轮询、短任务优先;
- 系统一般采取混合算法,因为不同进程特点不一样,单一的调度算法不能满足所有的场景;比如短任务算法需要在线程之间的切换消耗 和 任务真正执行的消耗,两者之间平衡,所以,每种调度算法都有自己的缺点和有点,混合算法是最高效的;
- 自旋锁在低等级的任务加锁之后占用了高等级任务所需要的资源。根据算法,如果中等级的任务不需要使用到这个被占用的资源,结果就是中等级任务分配的时间可能会多于高等级;
- 以上是高等级任务在等待时可以休眠的情况,也就是等待不是很占用cpu,这种情况下只是出现优先级反转,但是如果高优先级任务的等待是忙循环,也就会出现cpu把事件都分配给高级别任务,但是高级别任务又是忙循环,低级别任务无法获取cpu时间,最终就是死循环,系统可能会崩溃;
二、os_unfair_lock
- 休眠,不是忙等待,是互斥锁;
- iOS10之后才能使用,用于替换自旋锁;
三、pthread_mutex
- 跨平台;
- 互斥锁,等待属于休眠;
- 可以设置类型,有:默认(PTHREAD_MUTEX_NORMAL)、递归所(PTHREAD_MUTEX_RECUSIVE)、错误检查锁(PTHREAD_MUTEX_ERRORCHECK);
- normal类型的锁在创建时(pthread_mutex_init(&mutex,0))传空即可,另外两种锁需要使用pthread_mutex_attr_settype来设置;
- 需要使用destory进行销毁,attr、condition、mutex都需要销毁;
- 递归锁在递归时使用不会造成死锁问题;
- 递归锁:允许同一个线程对通一把锁重复加锁,加锁次数和解锁次数对应时才能解锁;
- 条件锁:pthread_cond_wait 和 pthread_cond_signal 配合使用;pthread_cond_wait(cond,mutex)会标记cond并解锁mutex,线程进入休眠,并且阻塞代码。当调用pthread_cond_signal(cond)之后,接收到信号后再对mutex进行加锁,然后继续执行代码;
- 条件所中的cond并不是类似于if else,而只是一个标记;
- 条件所一般用于解决线程以来问题,当一个线程任务的执行需要以来另一个线程任务的执行时使用,条件起到的是标记和传递的作用;
- 唤醒一个线程的等待使用pthread_cond_signal,唤醒所有等待的线程则使用广播方法:pthread_cond_broadcast
- 条件等待时,调用signal方法发送信号之后,wait方法其实不是只判断一次的,而是循环判断检测,如果这个锁没加锁成功,就继续等待,如果加锁成功就返回,继续执行后面的代码;所以,signal和unlock方法的调用顺序差别不大,只有在两者调用期间出现很大的延时操作时,wait方法会等待很久才加锁成功,继续执行后面代码。总之,逻辑不会受影响,只是时间问题,pthread_mutex内部已经考虑到这种问题,完成了解决方案的实现;
四、自旋锁和互斥锁
- step:按行执行代码;si:按行执行汇编代码;
- 自旋锁:忙等,相当于while循环,在汇编中的体现是:jne -> 0xxxxxx ,条件成立则跳转到指定地址循环执行;
- 互斥锁:等待时休眠,不占用cpu,类似于RunLoop;本质是:syscall,调用系统级别的函数去休眠并等待被唤醒的消息;
- OSSpinLoc是自旋锁,os_unfair_lock和pthread_mutex是互斥锁;
五、NSLock、NSRecusiveLock、NSCondition、NSConditionLock
- 是对pthread_mutex的封装,封装成了OC对象;
六、串行队列
- async和sync决定是否可以开启线程,队列表示任务的执行方式。
- 任务是一代码块为最小颗粒,而不是以一行代码为最小颗粒。代码块中的每一行代码默认都是同步执行;
- sync表示从队列中取出任务到当前线程执行,async表示从队列中取出任务异步执行。所以,如果sync+serial queue 结果就是:可以将需要同步的任务(抢占资源的任务)添加到同一个queue中然后同步执行,结果就是线程同步成功;
七、dispatch_semaphore
- dispatch_semaphore在初始化时需要使用create传入一个最大信号量;
- 最大信号量意味着最多又多少条线程可以同时执行,如果是1,那么就类似于串行队列,所以也可以实现线程同步
dispatch_semaphore_wait(semaphore,time)的作用:
- 当semaphore>0时,让当前线程直接继续执行,且dispatch_semaphore的值-1;
- 当semaphore<=0时,让当前线程阻塞在这句代码中,且让线程休眠等待;
- time表示如果需要等待,那么最长等多久需要返回,传now立马进行判断,传forever就一直等;
dispatch_semaphore_signal(semaphore)的作用:
- 让semaphore+1;
使用流程:
- 比如创建semaphore设置的最大信号量是5,有100个线程会执行到这句代码;
- 当第一次进入时,semaphore=5>0,所以就会让当前进入,继续执行并且dispatch_semaphore-1=4;
- 假设dispatch_semaphore_wait和dispatch_semaphore_signal之间的代码时耗时操作;
- 以此类推,当第五条线程进入之后,semaphore=0,而因为是耗时操作,所以100条线程都会执行到dispatch_semaphore_wait代码;
- 从第六条线程开始,因为dispatch_semaphore=0,线程被阻塞,剩余的95条线程如果在耗时操作没有完成之前,也就是没有调用dispatch_semaphore_signal之前,如果执行到dispatch_semaphore_wait,那么都会处于休眠等待的状态;
- 当最先进入的线程执行完耗时操作,调用dispatch_semaphore_signal,dispatch_semaphore+1>0,那么第六条线程就会从休眠中唤醒,继续执行后面的代码;
- 以此类推…所以当semaphore初始化时设置为1,那么只有一条线程能够访问共享资源,如此便实现了线程同步;
八、@synchronized
- 底层仍然是pthread_mutex,是使用的recusive创建的递归锁;
- 根据@synchronized(obj){}传入的对象,生成一个和对象对应的一把锁,存入到map表中;
- 关键字不能自动提示,因为存在性能问题,不被推荐使用;
九、性能对比
http://www.taodudu.cc/news/show-1912780.html
相关文章:
- semaphore的几种用法
- 难道栈空间有缓存?
- iOS实例、类、元类
- id和instancetype
- Advanced Graphics and Animations for iOS Apps
- ivar和property
- bound、frame、position、anchorPoint
- Java、OC、C/C++中的null
- iOS:Tagged Pointer
- sqlite3源码调试
- 红黑树、B树、B+树各自适用的场景
- 动态库的隐式链接和显示链接
- iOS:懒加载符号绑定流程
- 汇编:call和jmp
- code review的一些思考
- iOS:fishhook原理分析
- mach-O文件结构分析
- 设备唯一标志的解决方案
- iOS:主流启动优化方案浅析
- iOS:segment对齐原则
- HTTP缓存机制及其在iOS中的应用
- iOS:SideTable
- iOS:isa指针
- iOS底层:PAGEZERO的作用
- iOS图形学(三):屏幕成像原理
- iOS图形学(四):iOS中的绘图框架
- Java基础(一):简介和基础数据类型
- Java基础(二):面向对象
- Java:常量池
- Java基础(三):常用对象
iOS中的锁和线程同步相关推荐
- Linux线程同步(二)---互斥锁实现线程同步
一 why 先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 在博客&l ...
- JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用
转载自 http://blog.csdn.net/bigtree_3721/article/details/51296064 JAVA 中无锁的线程安全整数 AtomicInteger,一个提供原子操 ...
- iOS多线程各种安全锁介绍 - 线程同步
一.atomic介绍 github对应Demo:https://github.com/Master-fd/LockDemo 在iOS中,@property 新增属性时,可以增加atomic选项,ato ...
- IOS多线程系统学习之线程同步与线程通信
多线程编程是有趣的事情,它很容易突然出现"错误情况",这是由于系统的线程调度具有一定的随机性造成的.不过,即使程序偶然出现"错误情况",这是由于系统的线程调度具 ...
- python中gil锁和线程锁_Python线程——GIL锁、线程锁(互斥锁)、递归锁(RLock)...
GIL锁 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行 ...
- java 信号量 互斥锁_线程同步(互斥锁与信号量的作用与区别)
"信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里).而互斥锁是用在多线程多任务互斥的,一 ...
- iOS 中的网络请求 (同步请求、异步请求、GET请求、POST请求)
1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然 ...
- Python 线程(二):简单锁实现线程同步
Python中有两种锁,一个锁是原始的锁(原语), 不可重入,而另一种锁则是可重入的锁即递归锁.而是thread模块中,只提供了不可重入的锁,而在threading中则提供这两种锁. 可重入:当一个线 ...
- python中gil锁和线程锁_浅谈Python中的全局锁(GIL)问题
CPU-bound(计算密集型) 和I/O bound(I/O密集型) 计算密集型任务(CPU-bound) 的特点是要进行大量的计算,占据着主要的任务,消耗CPU资源,一直处于满负荷状态.比如复杂的 ...
- iOS中安全结束 子线程 的方法
一个典型的结束子线程的方法: 用 isFinished 检测子线程是否被完全kill掉 -(IBAction)btnBack:(id)sender {//释放内存 仅仅remove 并不会触发内存 ...
最新文章
- tomcat 多实例启动脚本
- centos在线安装svn
- C51 汇编 双层循环延时代码
- 深度学习之 Cascade R-CNN
- pip与conda简述
- Intel Core Enhanced Core架构/微架构/流水线 (3) - 流水线概述
- 那些除夕夜还在上BOSS直聘的人
- Pytorch的可视化工具tensorboardX
- uoml文档交换服务器,文档处理系统和方法
- Android成企业安全主要威胁的十大原因
- Android 手机做麦克风扩音器demo
- 各个地图经纬度转换工具类
- 计算机程序ppt,计算机和计算机程序.ppt
- 通达信接口官网与量化交易有联系吗?
- Hexo个人博客搭建教程
- 黑名单挂断电话及删除电话记录
- 易语言 上传文件到远程服务器,易语言与向远程服务器发送文件夹
- Nginx反向代理的两种配置方式
- 基金定投是什么?定投的特点?
- 【Mo 人工智能技术博客】图卷积网络概述及其在论文分类上的应用