GCD

271 阅读2分钟

dispatch_semphore 最多几个线程同时访问共享资源。

dispatch_sync 相当于 signal == 1 时的锁 而且 less error

所以政英那个tableview刷新 可优化成:

dispatch_sync(dispatch_get_mainqueue)


dispatch_async(serail_queue) 具备创建新线程的能力。 创建了一个串行队列,但是线程还是新的,比如在主线程调用这句话,就又创建了一个新的线程,只不过task是fifo一个接一个执行的。

The currently executing task runs on a distinct thread (which can vary from task to task)

dispatch_sync 没有创建新线程的能力

dispatch_sync(con_current) 虽然是异步队列,但还是再当前线程,所以还是顺序执行。


dispatch_async_group

dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);

把block 添加到队列 然后跟group相关联 group里面blocks都执行完时,

dispatch_group_notify 不阻塞当前线程 只是保证 添加到group的blocks都完成后 执行 notify里面的block

dispatch_group_wait 阻塞当前线程 (调用这个方法时的线程,不是 group里面添加的线程) 所以最好不要在 serail queue调用这个方法 (serail queue == main queue时, 线程为主线程, 所以直接卡主, 不为 main queue时, 阻塞调用wait方法时的线程,所以最好是concurrent queue 把线程切到一个新的)

 dispatch_async(syqueue, ^{
  
  ----> syqueue 不管是串行还是并行 都是创建了一个新的thread 不是main thread.
  

        NSLog(@"group_before_1, current thread = %@", [NSThread currentThread]);

        dispatch_group_t group = dispatch_group_create();


        dispatch_group_async(group, syqueue, ^{
        
        -----> 当 syqueue 为 concurrent queue 时, 应该是又切了一次,所以重新创建了一个跟wait是不同的thread, 所以block可以执行
        
        -----> 当 syqueue 为 serail queue 时, 因为最开始是在syqueue里,因为是serail, 这里应该没切到别的线程!! 所以在wait那里就卡住了, 这里block没执行。
        
        
            NSLog(@"group_2, current thread = %@", [NSThread currentThread]);
            [NSThread sleepForTimeInterval:1];
        });
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
        
        ---> wait 阻塞当前线程, 需要跟group绑定的blocks都执行完
        
          dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"group_3");
    });
    
        ---> notify 不阻塞当前线程, 直接往下走
        
        NSLog(@"group_after_4, current thread = %@", [NSThread currentThread]);

    });

dispatch_async(syqueue, 只要是 async 就可以切到新的线程 不管 queue是串行还是并行。

YYKit线程池:

第一次创建时, 根据优先级,创建了5个不同的pool (主要为context结构体)

queue 主要根据 qos 串行并行 这两个参数创建

个数根据当前CPU个数创建


typedef struct {
   const char *name;
   void **queues;
   uint32_t queueCount;
   int32_t counter;
} YYDispatchContext;


 static YYDispatchContext *YYDispatchContextCreate(const char *name,
                                                uint32_t queueCount,
                                                NSQualityOfService qos) {
   YYDispatchContext *context = calloc(1, sizeof(YYDispatchContext));
   if (!context) return NULL;
   context->queues =  calloc(queueCount, sizeof(void *));
   if (!context->queues) {
       free(context);
       return NULL;
   }
   if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
       dispatch_qos_class_t qosClass = NSQualityOfServiceToQOSClass(qos);
       for (NSUInteger i = 0; i < queueCount; i++) {
           dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0);
           dispatch_queue_t queue = dispatch_queue_create(name, attr);
           context->queues[i] = (__bridge_retained void *)(queue);
       }
       
           
   int count = (int)[NSProcessInfo processInfo].activeProcessorCount;         
           
          

复用时, 根据counter + 1 % count 来取

static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context) {
    uint32_t counter = (uint32_t)OSAtomicIncrement32(&context->counter);
    void *queue = context->queues[counter % context->queueCount];
    return (__bridge dispatch_queue_t)(queue);
}