GCD

作者: 廖小凡 | 来源:发表于2019-11-22 14:22 被阅读0次

一.队列

  1. 全局队列:dispatch_get_global_queue(),全局队列是并发队列,添加进这个队列的任务会并发执行,开启多条线程。
  2. 主队列:dispatch_get_main_queue(),主队列是串行队列,在主线程执行添加进队列的任务,任务是一个一个执行的,先进来的先执行。
  3. 自定义队列:dispatch_queue_t,自定义队列可以是串行,也可以是并发。

二.异步同步

  1. 异步:异步执行,会新开一条线程来执行任务,主队列除外,主队列异步,会将任务添加到队列上,主线程执行完当前任务就去执行添加进来的任务,dispatch_async(queue,^{ 任务 })。
  2. 同步:同步执行是在当前线程上执行任务,不会新开线程,dispatch_sync(queue,^{ 任务 })。

三.常用方法

  1. dispatch_after... : 延迟多少秒执行
    //DISPATCH_TIME_NOW:从现在开始执行
    //延迟多少秒
    //执行的代码块
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        NSLog(@"block");
    });
  1. dispatch_one ... : 只执行一次的操作,可以用来创建单例类,只初始化一次内存
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"1");
    });
  1. dispatch_barrier_async() : 控制任务的执行顺序,在它前面的先执行,前面的执行完才执行后面的
    //并发执行,先执行12,然后3,然后45
    dispatch_queue_t queue1 = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue1, ^{
        NSLog(@"1");
    });
    dispatch_async(queue1, ^{
        NSLog(@"2");
    });
    dispatch_barrier_async(queue1, ^{
        NSLog(@"3");
    });
    dispatch_async(queue1, ^{
        NSLog(@"4");
    });
    dispatch_async(queue1, ^{
        NSLog(@"5");
    });
  1. dispatch_group_t,dispatch_group_async,dispatch_group_notify : 队列组,先执行async的任务,再做notify的任务,一般用于并发队列,需要什么先做好,才能配置下一步,比如下载图片,更新UI。
    //打印结果为123随意顺序,后面d再打印done
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        NSLog(@"1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"2");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"3");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"done");
    });

四.死锁

就是线程柱塞,可能造成的原因:
一个串行队列,加了一个异步的任务,异步任务里面加了个同步操作在串行队列上,异步任务会新开一条线程去执行任务,执行到里面的同步任务,串行队列会执行这个同步任务,但是这时候异步操作还没结束,串行队列不能去执行同步任务,相互等待,就造成了死锁。

    //死锁,要主线程同步执行1
    dispatch_queue_t queue2 = dispatch_get_main_queue();
    dispatch_async(queue2, ^{
        dispatch_sync(queue2, ^{
            NSLog(@"1");
        });
    });

解决方法:
将同步任务改为异步,就会将任务添加到串行队列上,而且排在异步任务后面

五.信号量

dispatch_semapore提供了三个函数

  1. dispatch_semaphore_create : 创建一个Semaphore并初始化信号的总量
  2. dispatch_semaphore_signal : 发送一个信号,让信号总量加一
  3. dispatch_semaphore_wait : 可以使信号量总量减一,信号总量为0,就是一直等待,不为0就可以正常执行
   //保证串行队列多个线程,每次只有一个线程对数组添加数据
   dispatch_queue_t queue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   //创建一个信号为1的信号量
   dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
   NSMutableArray *array = [[NSMutableArray alloc]init];
   for (int i = 0; i < 1000; ++i) {
       dispatch_async(queue3, ^{
           //信号大于等于1的时候dispatch_semaphore_wait会将信号减一,然后返回,信号小于1的时候就等待
           dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
           [array addObject:[NSString stringWithFormat:@"%d",i]];
           //将信号加1
           dispatch_semaphore_signal(semaphore);  
       });
   }

可以实现同步并行队列
应用:YYCache框架里面就用了信号量来保证大容量缓存的线程安全

相关文章

  • 多线程之GCD

    GCD介绍 1、GCD简介 2、GCD任务和队列 3、GCD 的基本使用 4、GCD 线程间的通信 5、GCD 的...

  • 扩展GCD(求逆元,解同余方程等等)

    首先要知道gcd函数的基本性质:gcd(a,b)=gcd(b,a)=gcd(|a|,|b|)=gcd(b,a%b)...

  • iOS - GCD

    目录 GCD简介 GCD核心概念 GCD队列的使用 GCD的常见面试题 GCD简介 Grand Central D...

  • iOS-多线程:GCD

    GCD 简介 GCD 任务和队列 GCD 的使用步骤 GCD 的基本使用(6种不同组合区别) GCD 线程间的通信...

  • 浅析GCD

    GCD目录: 1. GCD简介 为什么要用GCD呢? GCD可用于多核的并行运算GCD会自动利用更多的CPU内核(...

  • 7.3 多线程-GCD

    多线程-GCD 多线程-GCD-串行并行 多线程-GCD.png GCD-线程的通讯、延时操作、定时器 GCD-线...

  • iOS 多线程--GCD

    一、GCD基本介绍 1.GCD简介 GCD是Grand Central Dispatch的缩写,GCD是苹果推出的...

  • 自用算法模板(JAVA版)

    一、数论 1)GCD GCD(求最大公约数) QGCD(快速GCD) extGCD(拓展GCD,解决ax + by...

  • GCD介绍

    一、GCD简单介绍 什么是GCD GCD优势 任务和队列 GCD有2个核心概念 GCD的使用就2个步骤 将任务添加...

  • 7.多线程基础(七)GCD加强

    1.GCD串行队列和并发队列 2.GCD延时执行 3.GCD线程组:(的作用) 4.GCD定时器: GCD的实现 ...

网友评论

      本文标题:GCD

      本文链接:https://www.haomeiwen.com/subject/npaodftx.html