iOS 底层原理

GCD

2019-12-03  本文已影响0人  和风细羽

GCD

队列与线程的关系

  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 - 多线程:数据竞争问题与线程同步方案

上一篇下一篇

猜你喜欢

热点阅读