DisPatch

235 阅读3分钟

一、单例

1、 单例的实现

单例的核心思想:就是通过状态的判断使得block只被调⽤⼀次。

单例的写法通常是这样:

static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
     // code
    });

单例的源码实现

image.png

  1. 把dispatch_once_t转换成dispatch_once_gate_t类型
  2. 如果l的状态为DLOCK_ONCE_DONE,说明block已经被执行了,直接返回
  3. 判断l的状态是是否为DLOCK_ONCE_DONE,若不是,则执行block
  4. 如果block正在执行,则一直等待 image.png

二、栅栏函数

栅栏函数的效果:等待栅栏函数前添加到队列⾥⾯的任务全部执⾏完成之后,才会执⾏栅栏函数⾥⾯的任务,栅栏函数⾥⾯的任务执⾏完成之后才会执⾏栅栏函数后⾯的队列⾥⾯的任务。

需要注意的点: 1. 栅栏函数只对同⼀队列起作⽤。 2. 栅栏函数对全局并发队列⽆效。 栅栏函数的写法:

// 栅栏函数

    dispatch_barrier_async(t, ^{

        // code

    });

barrier的直译是障碍,栅栏和分界线的意思!所以可以很直观的想到这个使用与在GCD中设置障碍用的! > 注意:barrier在全局队列中是不起作用的

  1. 源码全局队列里并没有处理栅栏函数
  2. 栅栏函数为什么要对全局队列无效?
  3. 全局队列不仅是给开发者使用,系统内部很多地方也使用到了全局队列,开发者不能影响操作系统的操作,故栅栏函数不能对全局例使用。

三、dispatch_group_t

调度组的效果:等待调度组前⾯的任务执⾏完才会执⾏dispatch_group_notify函数⾥⾯的任务。 调度组和队列没有关系,只要是同⼀调度组就可以。

dispatch_group_t g = dispatch_group_create();

    dispatch_queue_t que1 = dispatch_queue_create("lg1", DISPATCH_QUEUE_CONCURRENT);

    dispatch_queue_t que2 = dispatch_queue_create("lg2", DISPATCH_QUEUE_CONCURRENT);

    dispatch_group_async(g, que1, ^{

        // code

    });

    dispatch_group_enter(g);

    dispatch_async(que1, ^{

        sleep(2);

        NSLog(@"1");

        dispatch_group_leave(g);

    });

dispatch_group 通过一个状态值的设置, -- 控制组里面任务的执行顺序

四、信号量

dispatch_semaphore主要就是三个⽅法:

  1. dispatch_semaphore_create(long value);这个函数是创建⼀个dispatch_semaphore_t类型的信号量,并且创建的时候需要指定信号量的⼤⼩。

  2. dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); 等待信

号量。如果信号量值为0,那么该函数就会⼀直等待,也就是不返回(相当于阻塞当前线

程),直到该函数等待的信号量的值⼤于等于1,该函数会对信号量的值进⾏减1操作,然后返

回。

  1. dispatch_semaphore_signal(dispatch_semaphore_t deem); 发送信号量。该函数会对信号量

的值进⾏加1操作。

通过这三个⽅法,就能控制GCD的最⼤并发数量。

信号量在使⽤的时候需要注意: dispatch_semaphore_wait 和 dispatch_semaphore_signal ⼀定

要成对出现。因为在信号量释放的时候,如果dsema_orig初始信号量的⼤⼩⼤于dsema_value(通

过dispatch_semaphore_wait和dispatch_semaphore_signal改变之后的信号量的⼤⼩)就会触发崩

溃。

    // dispatch_semaphore_create -- 创建信号量  指定信号量的大小

    // dispatch_semaphore_signal -- 发送信号量 --将信号量的值+1

    // dispatch_semaphore_wait   等待信号量 --当信号量的值为0 阻塞线程, 一直等待,当信号量的值大于等于1的时候,信号量 -1

    

    // 能够控制并发数量
    dispatch_semaphore_t sem = dispatch_semaphore_create(2);

    

    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        sleep(1);

        NSLog(@"1");

        dispatch_semaphore_signal(sem);

    });
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

信号量容易crash, dispatch_semaphore_signal与dispatch_semaphore_wait必须要成双成对的出现,不然容易崩溃

五、dispatch_source

  1. dispatch_source_create 创建源
  2. dispatch_source_set_event_handler 设置源事件回调
  3. dispatch_source_merge_data 源事件设置数据
  4. dispatch_source_get_data 获取源事件数据
  5. dispatch_resume 继续
  6. dispatch_suspend 挂起
  7. dispatch_source_cancel 取消源事件