GCD详解 《一》

Grand Central Dispatch(GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。他是在线程池模式的基础上执行的并发任务。在Mac OS X 10.6 中首次推出,也可以在iOS 4以及以上版本使用。

GCD的优点

  1. 可以用于多核的并行运算
  2. 会自动利用更多的CPU内核
  3. 会自动管理线程的生命周期

GCD的队列(串行队列,并发队列)

  • 串行队列(Serial Dispatch Queue):每次只有一个任务被执行,让任务一个接着一个的执行,只有一个线程,一个任务执行完毕后,在执行下一个

  • 并发队列(Concurrent Dispatch Queue):可以开启多个线程,并同时执行多个任务

共同点:串行队列,并发队列都符合FIFO(先进先出)的原则,两者的区别在于执行顺序不同,开启的线程数不同

GCD的执行方式

  • 同步执行(sync):同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后在执行。(只能在当前线程中执行任务,不具备开启新线程的能力)

  • dispatch_get_main_queue()是一种特殊的串行队列

  • 异步执行(async):异步添加任务到指定的队列中吗,它不会做任何等待,可以继续执行任务。()可以在新的线程中执行任务,具备开启新线程的能力。

放到并行队列的任务,如果是异步执行,GCD也会FIFO的取出来,但不同的是,它取出来一个就会放到别的线程,然后再取出来一个又放到另一个的线程。这样由于取的动作很快,忽略不计,看起来,所有的任务都是一起执行的。不过需要注意,GCD会根据系统资源控制并行的数量,所以如果任务很多,它并不会让所有任务同时执行。

队列 同步执行 异步执行
串行队列 当前线程,一个一个执行 其他线程,一个一个执行
并发队列 当前线程,一个一个执行 开很多线程,一起执行
  1. 串行同步执行 ( 当前线程,一个一个执行)
  dispatch_queue_t queue = 
                     dispatch_queue_create("demo",DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue, ^{
        NSLog(@"任务1---%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"任务2---%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"任务3---%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"任务4---%@",[NSThread currentThread]);
    });

  /*输出结果
      任务1---{number = 1, name = main}
      任务2---{number = 1, name = main}
      任务3---{number = 1, name = main}
      任务4---{number = 1, name = main}
 */
  1. 串行异步执行 ( 其他线程,一个一个执行)
dispatch_queue_t queue =
               dispatch_queue_create("demo", DISPATCH_QUEUE_SERIAL);
   
    dispatch_async(queue, ^{
        NSLog(@"任务1---%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"任务2---%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"任务3---%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"任务4---%@",[NSThread currentThread]);
    });
    
    /*输出结果
       任务1---{number = 6, name = (null)}
       任务2---{number = 6, name = (null)}
       任务3---{number = 6, name = (null)}
       任务4---{number = 6, name = (null)}
     */
  1. 并发同步执行 ( 当前线程,一个一个执行)
dispatch_queue_t queue =
               dispatch_queue_create("demo", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_sync(queue, ^{
        NSLog(@"任务1---%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"任务2---%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"任务3---%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"任务4---%@",[NSThread currentThread]);
    });
    
    /*输出结果
       任务1---{number = 1, name = main}
       任务2---{number = 1, name = main}
       任务3---{number = 1, name = main}
       任务4---{number = 1, name = main}
     */
  1. 并发异步执行 ( 开很多线程,一起执行)
dispatch_queue_t queue = 
          dispatch_queue_create("demo", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"任务1---%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"任务2---%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"任务3---%@",[NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"任务4---%@",[NSThread currentThread]);
    });
    
    /*输出结果
        任务2---{number = 6, name = (null)}
        任务3---{number = 5, name = (null)}
        任务1---{number = 7, name = (null)}
        任务4---{number = 8, name = (null)}
     */

如果在主队列中执行同步操作会怎么样?

截屏2020-10-21 下午3.51.01.png

从图中看出,程序直接崩溃了,原因:
主队列是一个特殊的串行队列,串行队列的特点是当前一个任务执行完才能执行下一个任务。也就是只有在任务1之前加入的任务完成才能执行任务1,而同步执行的特点是在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后在执行,也就是在任务1之前加入的任务要想完成,必须要等任务1完成,而任务1完成就必须等待之前的任务完成,这就造成了死锁导致了程序的崩溃。

例子

dispatch_queue_t queue = dispatch_queue_create("demo",DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"任务1");
        //下面程序就在输出1后,奔溃了
        dispatch_sync(queue, ^{
            NSLog(@"任务2");
        });
        NSLog(@"任务3");
   });

原因:
这是一个串行队列,首先执行了任务1,之后同步插入了任务2。要想执行任务2,就必须先执行完任务3,但是想要执行任务3,就必须把任务2 执行完成,导致了死锁,程序奔溃。

你可能感兴趣的:(GCD详解 《一》)