iOS多线程

dispatch_group_async

队列组, 异步执行, 等所有任务执行完毕, 会执行dispatch_group_notify, 这种之前应用场景是同时异步下载多张图片的操作, 等到所有图片现在完毕, 拿到图片进行拼接.

dispatch_group_t group = dispatch_group_create();

NSMutableArray *mua = [NSMutableArray array];

for (YSPatientModel *model in groupModel.members) {
    
    if (model.pic) {
        dispatch_group_enter(group);

        [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:model.pic] options:0 progress:nil completed:^(UIImage* image, NSError* error, SDImageCacheType cacheType, BOOL finished, NSURL* imageURL) {
            if (image) {
                [mua addObject:image];
            }
//                        NSLog(@"线程%@",[NSThread currentThread]);
            dispatch_group_leave(group);
        }];
        
    }
    
}

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    
    UIImage *resultImage = [UIImage composeHeaderImageWithConstrainWH:self.groupIconImg.bounds.size.width imagePathArray:mua backgroundColor:RGB(236, 236, 236)];
    self.groupIconImg.image = resultImage;
    
});

dispatch_barrier_async 栅栏

同一队列, 异步执行时,barrier块必须单独执行,不能与其他block并行。这只对并发队列有意义,并发队列如果发现接下来要执行的block是个barrier block,那么就一直要等到当前所有并发的block都执行完毕,才会单独执行这个barrier block代码块,等到这个barrier block执行完毕,再继续正常处理其他并发block。

dispatch_queue_t queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, ^{
    NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
    NSLog(@"----2-----%@", [NSThread currentThread]);
});

//  都会等待在它前面插入队列的任务(1、2、)先执行完再执行后面的任务(3, 4)
dispatch_barrier_async(queue, ^{
    NSLog(@"----barrier-----%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"----3-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
    NSLog(@"----4-----%@", [NSThread currentThread]);
});

dispatch_semaphore 信号量

防止多个线程同时操作一块资源, 控制并发。dispatch_semaphore_create 可以理解为创建的信号总量,dispatch_semaphore_signal是发送一个信号,会让信号总量加1,dispatch_semaphore_wait等待信号,让信号总量-1,当信号总量少于等于0的时候就会一直等待,否则就可以正常的执行,可以创建一个并发控制。YYCache里有用到。

dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
// 异步3个线程访问2个资源, 只分配2个资源
    
//任务1
dispatch_async(quene, ^{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"run task 1");
    
    dispatch_semaphore_signal(semaphore);
    NSLog(@"complete task 1");
});
//任务2
dispatch_async(quene, ^{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"run task 2");

    dispatch_semaphore_signal(semaphore);
    NSLog(@"complete task 2");
});
//任务3
dispatch_async(quene, ^{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"run task 3");

    dispatch_semaphore_signal(semaphore);
    NSLog(@"complete task 3");
});

当然, 底下 NSLock锁 一样可以实现以上操作。

NSLock锁

NSLock *lock = [[NSLock alloc]init];
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//任务1
dispatch_async(quene, ^{
    
    [lock lock];
    NSLog(@"run task 1");
    sleep(5);
    
    [lock unlock];
    
    NSLog(@"complete task 1");
});
//任务2
dispatch_async(quene, ^{
    
    [lock lock];
    NSLog(@"run task 2");
    
    [lock unlock];
    NSLog(@"complete task 2");
});
    
// 打印结果
//    2017-08-10 16:29:44.792 GCDSemaphore[8153:2775304] run task 1
//    2017-08-10 16:29:49.797 GCDSemaphore[8153:2775302] run task 2
//    2017-08-10 16:29:49.797 GCDSemaphore[8153:2775304] complete task 1
//    2017-08-10 16:29:49.797 GCDSemaphore[8153:2775302] complete task 2

当任务1锁住之后,任务2会一直等待5s后等任务1将锁设置为unlock后,才会执行run task 2。如果不unlock, 那么任务2永远不会执行