文章必须有一个前言:
在默默coding的时候,涉及到了一个点,就是某块代码的执行受到某一个变量的限制,如果当前变量为YES,则可以执行此块代码,但并不知道这个变量会在什么时候设置为YES;比较直接的思路就是监听变量值得变化,从而决定是否执行代码;不过还是想看看有没有更好(高大上)的方式,于是乎思虑万千,“等待”、“允许执行”、、、这几个词语轮回旋转,wait,对哦,信号量是个好东西,由此有了今天的一篇小知识点文章;
注意,正文了:
信号量:多用于多线程中,在多线程开发的过程中不可避免的会涉及到并发的问题,尤其是在我们并不想让某些关键代码被并发执行的时候,可以使用信号量来解决;在描述到这个话题的时候,不可避免的会想到@synchronized 同步锁,在某些情况下同步锁也能解决我们多线程共同访问关键代码的问题。
自我的理解看来(代码一和代码二都会触发关键代码)
1.同步锁:代码一和代码二都回去敲一下关键代码的门,而后在门口进行等待,等待被允许进入;信号量:代码一和代码二都在各自的家中等着通知,当被通知可以进行访问的时候,代码一和代码二将会从家出发去关键代码,并且直接进门
2.通过第一点的描述也可以看出另外一个问题,同步锁不会执行顺序的规则,来者不拒;而信号量绘指定一个顺序也就是需要先排好队(考虑这个问题,请忽略信号量可以限制多个资源共同访问的现象)
3.通过第二点衍生出这个问题,信号量是可以制定访问规则为多个资源功能访问;而同步锁就比较尴尬了,只能One by One,前者不出来,后者就是进不去。(是不是屋子太小了,容不下两个人,哈哈)
实际场景:代码一和代码二都需要触发关键代码来进行后续操作,那么代码一和代码二都需要去获取信号量,当代码一被允许执行的时候,会成功调用关键代码,且在关键代码调用成功的时候会释放信号量,当代码二接收到信号量被释放的信号,这意味着代码二就可以进入执行了。
小二,上一个变量给我,速度的:
// 计数信号量
dispatch_semaphore_t semaphore;
再给我来点解饿的,要硬菜,特别硬:(创建一个计数值为0的信号量)
if (!semaphore) {
/*!
* Apple Documentation : dispatch_semaphore_t dispatch_semaphore_create(long value);
*
* 创建具有初始值的新计数信号量 : 在这里我们设置为0,这意味着信号量创建之后将意味着dispatch_semaphore_wait之后的代码不可执行(wait在后续介绍)
*
* 要点1 : 当两个线程需要协调特定事件的完成时,为值传递零是有用的
* 要点2 : 传递大于零的值对于管理有限的资源池非常有用,其中池大小等于该值
*
* 注意 : 信号量的起始值传递小于零的值将导致返回NULL
*/
semaphore = dispatch_semaphore_create(0);
}
什么?我的硬菜还得等会?那什么时候能好,行吧,那我等会吧(使用信号量的话,每一个执行点都需要调用wait函数等待,等待被唤醒)
//创建异步执行的环境(Apple Documentation : 提交一个用于在调度队列上进行异步执行的代码块)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
/*!
* semaphore - 等待(减少)信号量
*
* @param semaphore
* @param DISPATCH_TIME_FOREVER 永远等待
*
* 返回值:
* 1. 如果结果值小于零,则此函数在返回之前等待信号发生
* 2. 如果结果值非零,则线程被唤醒
*/
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//处理被唤醒的代码
//返回主线程处理UI
dispatch_async(dispatch_get_main_queue(), ^{
//show the view
});
});
等待了N久,已经饿得不行了,通过观察得知,硬菜已经做好了,但是小二在刷盘子没空上菜,不过,哼哼。俗话说技多不压身,通过学习的代码技能,调整一下小二的工作,于是写下了如下代码,然后小二就立即把菜端了上来。可以吃了。
/*!
* semaphore +1 : broken the forever waiting
* 增加计数信号量。如果前一个值小于零,则此函数在返回之前唤醒等待的线程。写在wait后面的代码(dispatch_semaphore_wait)
*/
dispatch_semaphore_signal(semaphore);