多线程线程同步方案

线程同步问题

文章目录

  • 线程同步问题
    • OSSpinLock
    • os_unfair_lock
    • pthread_mutex
      • pthread_mutex 互斥锁
      • pthread_mutex 递归锁
      • pthread_mutex 条件锁
    • NSLock、NSRecursiveLock
    • NSCondition
    • NSConditionLock
    • dispatch_semaphore
    • dispatch_queue(DISPATCH_QUEUE_SERIAL)
    • @synchronized
    • 线程同步方案性能比较
    • 自旋锁、互斥锁比较
    • iOS中的读写安全方案

OSSpinLock

  • 已不安全,不推荐使用

  • OSSpinLock叫做”自旋锁”,等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源

  • 目前已经不再安全,可能会出现优先级反转问题

    • 如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放锁(优先级比较低的线程一直拿不到CPU 就无法释放锁,优先级高的一直拿不到锁,就处于死锁状态)
    • 需要导入头文件 #import

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RTv3htlD-1586360075303)(media/15414898062564/15816946374692.jpg)]

os_unfair_lock

  • os_unfair_lock用于取代不安全的OSSpinLock ,从iOS10开始才支持

  • 从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等

  • 需要导入头文件#import

  • 实际上也是互斥锁

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsW5RfmD-1586360075304)(media/15414898062564/15816950992558.jpg)]

pthread_mutex

pthread_mutex 互斥锁

  • mutex叫做”互斥锁”,等待锁的线程会处于休眠状态

  • 需要导入头文件#import

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6VvTtNt-1586360075305)(media/15414898062564/15816980650497.jpg)]

pthread_mutex 递归锁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZoeOXbG-1586360075307)(media/15414898062564/15817860472078.jpg)]

pthread_mutex 条件锁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sl5w6GDc-1586360075308)(media/15414898062564/15817861101084.jpg)]

NSLock、NSRecursiveLock

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJsiEVFh-1586360075309)(media/15414898062564/15817861562700.jpg)]

NSCondition

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQJigzbv-1586360075312)(media/15414898062564/15817870358064.jpg)]

NSConditionLock

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGA3T6uF-1586360075313)(media/15414898062564/15817870542568.jpg)]

dispatch_semaphore

  • semaphore叫做”信号量”
  • 信号量的初始值,可以用来控制线程并发访问的最大数量
  • 信号量的初始值为1,代表同时只允许1条线程访问资源,保证线程同步

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ml3oQZSU-1586360075315)(media/15414898062564/15817871175345.jpg)]

dispatch_queue(DISPATCH_QUEUE_SERIAL)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Fve9wXl-1586360075316)(media/15414898062564/15817871453934.jpg)]

@synchronized

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DfwJYxg7-1586360075317)(media/15414898062564/15817871634320.jpg)]

线程同步方案性能比较

  • 性能从高到低排序
    • os_unfair_lock (不公平的 iOS10开始使用,10以前版本不支持)
    • OSSpinLock (spin 旋转 不推荐使用)
    • dispatch_semaphore (推荐使用)
    • pthread_mutex (mutex 互斥) (推荐使用)
    • dispatch_queue(DISPATCH_QUEUE_SERIAL)
    • NSLock
    • NSCondition
    • pthread_mutex(recursive)
    • NSRecursiveLock
    • NSConditionLock
    • @synchronized

自旋锁、互斥锁比较

  • 什么情况使用自旋锁比较划算?

    • 预计线程等待锁的时间很短
    • 加锁的代码(临界区)经常被调用,但竞争情况很少发生
    • CPU资源不紧张
    • 多核处理器
  • 什么情况使用互斥锁比较划算?

    • 预计线程等待锁的时间较长
    • 单核处理器
    • 临界区有IO操作
    • 临界区代码复杂或者循环量大
    • 临界区竞争非常激烈

iOS中的读写安全方案

  • 思考如何实现以下场景

    • 同一时间,只能有1个线程进行写的操作
    • 同一时间,允许有多个线程进行读的操作
    • 同一时间,不允许既有写的操作,又有读的操作
  • 上面的场景就是典型的“多读单写”,经常用于文件等数据的读写操作,iOS中的实现方案有

    • pthread_rwlock:读写锁

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-swpFVImT-1586360075318)(media/15414898062564/15818728584498.jpg)]

    • dispatch_barrier_async:异步栅栏调用

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9N6CRpT8-1586360075325)(media/15414898062564/15818728827852.jpg)]
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RUUjlnE6-1586360075326)(media/15414898062564/15818729092686.jpg)]

你可能感兴趣的:(iOS)