文章必须有一个前言:

在默默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);