iOS--关于GCD的一些疑惑

Posted six6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS--关于GCD的一些疑惑相关的知识,希望对你有一定的参考价值。

讲解GCD的资料看了好多,但都没有解决心中的疑惑

  1.主队列只有一个线程,那么同步和异步执行有什么区别?同步主线程会造成线程死锁,异步不会,为什么呢?

  2.同步执行串行队列和同步执行并行队列,有什么区别?同步执行,是在当前线程中执行队列中的任务,就意味着任务都在一条线程中执行,不可能多任务同时执行啊。

  3.在主线程中同步执行串行队列,为什么就不造成线程死锁呢?

 

有疑不解,如鲠在喉。有疑惑就代表学得不到位,概念理解不够。因此,我开始重头学习GCD,理清这些基础概念

 

有4个术语比较容易混淆:同步、异步、并发、串行

同步和异步决定了要不要开启新的线程

  同步:在当前线程中执行任务,不具备开启新线程的能力

  异步:在新的线程中执行任务,具备开启新线程的能力

并发和串行决定了任务的执行方式

  并发:多个任务并发(同时)执行

  串行:一个任务执行完毕后,再执行下一个任务

组合一下:

  1. 同步执行串行队列
  2. 同步执行并发队列
  3. 异步执行串行队列
  4. 异步执行并发队列
  5. 同步执行主队列
  6. 异步执行主队列

我加入了主队列(只有一条线程的串行队列),是因为它和一般的串行队列有些区别。下面我就对这6种情况逐个分析

1.同步执行串行队列:在当前线程中,逐一执行队列中的任务。

2.同步执行并发队列:同1

3.异步执行串行队列:开启一条新线程,逐一执行队列中的任务。

4.异步执行并发队列:开启多条线程,同时执行队列中的多个任务。

先理清这四种情况的嵌套执行,在讲主线的两种情况。

下面就是大堆代码了,对照代码和打印结果进行思考,看有没有自己觉得解释不通的

demo地址:https://github.com/jiliuliu/FoundationOC

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        dispatch_queue_t backgroundSerialQueue = dispatch_queue_create("backgroundSerialQueue", DISPATCH_QUEUE_SERIAL);
        
        dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
        
        //避开主线程,单独开启一个线程做测试
        dispatch_async(backgroundSerialQueue, ^{
            NSLog(@"%@", [NSThread currentThread]);
            
            dispatch_sync(serialQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(serialQueue)1");
            });
            dispatch_sync(serialQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(serialQueue)2");
            });
            dispatch_sync(serialQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(serialQueue)3");
            });
            
            NSLog(@"************************");
            
            dispatch_sync(concurrentQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(concurrentQueue)1");
            });
            dispatch_sync(concurrentQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(concurrentQueue)2");
            });
            dispatch_sync(concurrentQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(concurrentQueue)3");
            });
            
        });
    }
    NSLog(@"----exit----");
    return 0;
}

打印结果:

----exit----
<NSThread: 0x10064f1b0>{number = 2, name = (null)}

感觉和预想的那里不对,于是修改下:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        dispatch_queue_t backgroundSerialQueue = dispatch_queue_create("backgroundSerialQueue", DISPATCH_QUEUE_SERIAL);
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        
        dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
        
        //避开主线程,单独开启一个线程做测试
        dispatch_async(backgroundSerialQueue, ^{
            NSLog(@"%@", [NSThread currentThread]);
            
            dispatch_sync(serialQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(serialQueue)1");
            });
            NSLog(@"dispatch_sync(serialQueue)1--");
            dispatch_sync(serialQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(serialQueue)2");
            });
            NSLog(@"dispatch_sync(serialQueue)2--");
            dispatch_sync(serialQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(serialQueue)3");
            });
            NSLog(@"dispatch_sync(serialQueue)3--");
            
            NSLog(@"************************");
            
            dispatch_sync(concurrentQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(concurrentQueue)1");
            });
            NSLog(@"ispatch_sync(concurrentQueue)1--");
            dispatch_sync(concurrentQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(concurrentQueue)2");
            });
            NSLog(@"ispatch_sync(concurrentQueue)2--");
            dispatch_sync(concurrentQueue, ^{
                [NSThread sleepForTimeInterval:0.01];
                NSLog(@"dispatch_sync(concurrentQueue)3");
            });
            NSLog(@"ispatch_sync(concurrentQueue)3--");
            
            dispatch_barrier_sync(serialQueue, ^{
                dispatch_semaphore_signal(semaphore);
            });
            dispatch_barrier_sync(concurrentQueue, ^{
                dispatch_semaphore_signal(semaphore);
            });
        });
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    }
    
    NSLog(@"----exit----");
    return 0;
}

打印结果:

<NSThread: 0x100600170>{number = 2, name = (null)}
dispatch_sync(serialQueue)1
dispatch_sync(serialQueue)1--
dispatch_sync(serialQueue)2
dispatch_sync(serialQueue)2--
dispatch_sync(serialQueue)3
dispatch_sync(serialQueue)3--
************************
dispatch_sync(concurrentQueue)1
ispatch_sync(concurrentQueue)1--
dispatch_sync(concurrentQueue)2
ispatch_sync(concurrentQueue)2--
dispatch_sync(concurrentQueue)3
ispatch_sync(concurrentQueue)3--
----exit----

对,就应该是这样的。

5.同步执行主队列:

6.异步执行主队列:

 

以上是关于iOS--关于GCD的一些疑惑的主要内容,如果未能解决你的问题,请参考以下文章

关于深度学习代码中一些疑惑的总结

关于深度学习代码中一些疑惑的总结

iOS —— 关于GCD的理解和使用

Ios小白必知的GCD术语

iOS 多线程:『GCD』详尽总结

比赛NOIP2017 小凯的疑惑