GCD

作者: 和风细羽 | 来源:发表于2019-12-03 21:10 被阅读0次

GCD

队列与线程的关系

  • 主队列和主线程

  • 『ios』主线程 和 主队列的关系,绝对安全的UI操作,主线程中一定是主队列?

    - (void)testInMainThread
    {
        // 异步提交任务到主队列
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"1 --- %@", [NSThread currentThread]); 
            self.label.backgroundColor = [UIColor orangeColor];  // 正常
        });
    
        // 同步提交任务到自定义并发队列
        dispatch_sync(dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT), ^{
            NSLog(@"2 --- %@", [NSThread currentThread]);
            self.label.backgroundColor = [UIColor greenColor];  // 正常
        });
    
        // 同步提交任务到自定义串行队列
        dispatch_sync(dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL), ^{
            NSLog(@"3 --- %@", [NSThread currentThread]); 
            self.label.backgroundColor = [UIColor whiteColor];  // 正常
        });
    }
    
    2 --- <NSThread: 0x6000039a1400>{number = 1, name = main}
    3 --- <NSThread: 0x6000039a1400>{number = 1, name = main}
    1 --- <NSThread: 0x6000039a1400>{number = 1, name = main}
    
  1. 队列不是线程。队列用来组织任务,线程是执行队列中的任务。
  2. 主队列是一个特殊的串行队列,异步提交任务到主队列不会开辟新线程。
  3. 一个线程可以执行多个队列中的任务。
  4. 只要在主线程,主队列、自定义的串行/并发队列任务都能够刷新 UI。
  5. 主队列不一定在主线程执行,比如:人为调用 dispatch_main()。

死锁

用 dispatch_sync 添加任务到它自己所在的串行队列中就会造成死锁。

死锁的三个条件:

  1. dispatch_sync(同步)添加任务
  2. 串行队列
  3. 添加的任务和 dispatch_sync 在同一个队列
- (void)testInMainThread
{
    // 情形 ①、dispatch_sync 自身在主队列
    dispatch_sync(dispatch_get_main_queue(), ^{        

    });

    dispatch_queue_t queue = dispatch_queue_create("CONCURRENT", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        // 情形 ②、dispatch_sync 自身在 queue 队列
        dispatch_sync(queue, ^{
            NSLog(@"222");
        });
    });
}

解决方案就是让死锁的三个条件中任意一个不满足即可。

读写安全方案

  • 同一时间,只允许一个线程执行写入操作
  • 同一时间,许多个线程都执行读取操作
  • 同一时间,不能既有写入操作,也有读取操作

方案:

  1. dispatch_semaphore 信号量,缺陷是不能实现允许多个线程读取操作
  2. dispatch_barrier_async 栅栏,注意读写任务队列必须是自己创建的并发队列
  3. pthread_rwlock 读写锁

多线程:GCD

数据竞争

多个线程并发执行,同一时间访问同一块数据(如同一个变量、对象、文件等),就有可能出现数据竞争,从而导致数据错乱。

线程同步

方案:

  1. 加锁。多个线程使用同一把锁,对访问数据的关键代码进行加锁;
    • OSSpinLock 自旋锁
    • os_unfair_lock 互斥锁
    • pthread_mutex 互斥锁
    • NSLock 互斥锁
    • NSRecursiveLock 递归锁
    • @synchronized
  2. 设置线程的最大并发数为 1
  3. 把多个线程放入串行队列

其中方案 2 和 3 差不多。

意一ineyee - 多线程:数据竞争问题与线程同步方案

相关文章

  • 多线程之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/ozphgctx.html