美文网首页
多线程 (锁)学习

多线程 (锁)学习

作者: Tony17 | 来源:发表于2020-02-28 08:59 被阅读0次

    前言

    多线程在开发过程中使用非常频繁,但是由于 OC GCD的强大和客户端对于多线程的需求没有那么复杂。很多时候就是一个简单的调用就可以满足我们的需求,但是随着项目的增大,简单的开启异步线程已经不能瞒住我们的需要。今天我来简单学些一下多线程的知识。

    多线程

    thread_all.png

    同步,异步,并发,串行

    • 同步和异步的主要影响: 能不能开启新的线程
      • 同步: 在当前线程中执行任务,不具备开启新线程的能力
      • 异步: 在新的线程中执行任务,具备开启新线程的能力
    • 并发和串行的主要影响: 任务的执行方式
      • 并发: 多个任务同时执行,只有在异步函数下才有效
      • 串行: 一个任务执行完毕后,开始执行下一个任务
    thread_sync_async.png

    多线程隐患

    多线程最常见的隐患是资源共享,当多个线程同时访问同一块资源的时候,容易引发数据错乱和数据安全问题。
    解决办法是线程同步技术,实现同时只会有一个线程访问资源已解决资源共享的问题。
    最常见的线程同步技术是 加锁

    线程同步方案

    以下说明按照性能从高到低排序:

    • os_unfair_lock
      • 用于取代不安全的 OSSpinLock,从iOS 10才开始支持
      • 属于互斥锁,会让等待锁的线程处于休眠状态,并非忙等
      • 需要导入头文件 <os/lock.h>
    • OSSpinLock
      • 自旋锁,等待锁的线程会处于忙等状态,一直占用CPU资源
      • 已经不再安全,会出现优先级反转导致死锁问题
      • 需要导入头文件 <libkern/OSAtomic.h>
    • dispatch_semaphore
      • 信号量,初始值可以控制线程并发访问的最大数量
      • 如果初始值为1,代表同时只能有1个线程访问资源,保持同步
    • pthread_mutex
      • 互斥锁,等待锁的线程会处于休眠状态
      • 需要导入头文件 <pthread.h>
      • 递归锁也是通过互斥锁实现的
      • 通过设置不同的属性值,实现不同类型的锁 PTHREAD_MUTEX_RECURSIVE 就是递归锁
    • dispatch_queue(DISPATCH_QUEUE_SERIAL)
      • GCD串行队列,可以实现锁的功能
    • NSLock
      • 对 mutex 普通锁的封装
    • NSCondition
      • 对 mutex 和 cond 的封装
    • pthread_mutex(recursive)
      • 递归锁
    • NSRecursiveLock
      • 对 mutex 递归锁的封装,API 跟 NSLock 基本一致
    • NSConditionLock
      • NSCondition 进一步的封装
    • @synchronized
      • 对 mutex 递归锁的封装
      • @synchronized(obj) 内部会生成 obj 对应的递归锁,然后进行加锁,解锁操作

    属性的 atomic 修饰符用于保证属性的 setter、getter 的原子性操作,相当于在 getter、setter 内部价了线程同步的锁,但是它并不能保证使用属性的过程中是线程安全的

    互斥锁,自旋锁比较

    • 什么时候选用自旋锁比较划算
      • 预计线程等待锁的时间很短
      • 加锁代码(临界区)经常被调用,但竞争很少发生
      • CPU 资源不紧张
      • 多核处理器
    • 什么时候选用互斥锁比较划算
      • 预计线程等待时间比较长
      • 单核处理器
      • 临界区有 IO 操作
      • 临界区代码复杂或者循环量大
      • 临界区竞争非常激烈
      • 递归锁是特殊的互斥锁,允许同一线程重复加锁

    iOS中的读写安全方案

    典型的应用场景是多读单写,经常用于文件等数据的读写操作,iOS中的实现方案有:

    • pthread_rwlock:读写锁
      • 等待锁的线程会进入睡眠
    • dispatch_barrier_async:异步栅栏调用
      • 必须传入自己创建的并发队列
      • 如果传入一个串行队列或者全局的并发队列,这个函数的效果相当于 dispatch_async 函数

    最后

    以上就是本篇的内容,势必会有一些遗漏和错误,欢迎斧正~

    相关文章

      网友评论

          本文标题:多线程 (锁)学习

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