iOS GCD 串行和并发队列的理解

2019-05-24  本文已影响0人  大风天上来

首先看串行队列同步异步任务的请求顺序

/**
 测试串行队列
 */
- (void)testSerialQueue {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(serialQueue, ^{
        NSLog(@"1 %@", [NSThread currentThread]);
    });
    
    dispatch_async(serialQueue, ^{
        sleep(5);
        NSLog(@"2 %@", [NSThread currentThread]);
    });
    
    dispatch_sync(serialQueue, ^{
        NSLog(@"3 %@", [NSThread currentThread]);
    });
    
    dispatch_async(serialQueue, ^{
        NSLog(@"4 %@", [NSThread currentThread]);
    });
}

运行结果


串行队列,同步异步任务执行

运行结果显示:任务依次执行,异步会创建新线程。

看看并行队列异步任务的执行结果

- (void)testSerialQueue {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0 ; i < 20; i ++) {
        dispatch_async(serialQueue, ^{
            NSLog(@"%d %@",i, [NSThread currentThread]);
        });
    }
}
并行队列,异步任务

从运行结果可以看出,并发会创建多个线程,而且并发队列中的线程是可以重复利用的(线程池)。

并发队列的同步任务

- (void)testSerialQueue {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0 ; i < 20; i ++) {
        dispatch_sync(serialQueue, ^{
            NSLog(@"%d %@",i, [NSThread currentThread]);
        });
    }
}
并发队列,同步任务

从运行结果可以看出,并发队列的同步任务,没有创建新的线程,都在主线程依次执行

串行队列同步任务的执行顺序

/**
 测试串行队列
 */
- (void)testSerialQueue {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_SERIAL);
    
    NSLog(@"this is mainQueue-0 %@", [NSThread currentThread]);
    dispatch_sync(serialQueue, ^{
        NSLog(@"1 %@", [NSThread currentThread]);
    });
    NSLog(@"this is mainQueue-1 %@", [NSThread currentThread]);

    dispatch_sync(serialQueue, ^{
        NSLog(@"2 %@", [NSThread currentThread]);
    });

    NSLog(@"this is mainQueue-2 %@", [NSThread currentThread]);
}
串行队列,同步任务

结论:本来我预测的执行结果是

this is mainQueue-0
this is mainQueue-1
this is mainQueue-2
1
2

因为没有考虑到同步任务会阻塞当前线程。前面提到串行队列中的任务,按照FIFO的方式依次执行。但是如果考虑到阻塞的问题,后面的任务是没有进入队列的。

串行队列 同步任务 嵌套

串行队列,嵌套同步任务,阻塞当前线程,线程陷入死锁。
既阻塞了当前线程、又想在当前线程末尾执行。

串行队列嵌套任务 串行队列嵌套异步任务

执行结果

执行结果

分析:嵌套内的同步任务会阻塞当前线程,并且陷入死锁。嵌套内的异步任务不会阻塞当前线程

/**
 测试并行队列同步任务 嵌套
 */
- (void)testSerialQueue {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.snake", DISPATCH_QUEUE_CONCURRENT);
    
    NSLog(@"this is mainQueue-0 %@", [NSThread currentThread]);
    dispatch_sync(serialQueue, ^{
        NSLog(@"1 %@", [NSThread currentThread]);
        dispatch_sync(serialQueue, ^{
            NSLog(@"inside task %@", [NSThread currentThread]);
        });
    });
    NSLog(@"this is mainQueue-1 %@", [NSThread currentThread]);

    dispatch_sync(serialQueue, ^{
        NSLog(@"2 %@", [NSThread currentThread]);
        dispatch_sync(serialQueue, ^{
            NSLog(@"inside task 2 %@", [NSThread currentThread]);
        });
    });

    NSLog(@"this is mainQueue-2 %@", [NSThread currentThread]);
}

并行队列,同步任务

测试并行队列同步任务的执行顺序

结论:

串行队列,同步任务会阻塞当前线程,嵌套内的同步任务会产生死锁;

参考:

iOS 之GCD串行和并发队列的理解
iOS基础深入补完计划--多线程(面试题)汇总

上一篇下一篇

猜你喜欢

热点阅读