探尋iOS多線程

iOS中的常見(jiàn)多線程方案

image.png

GCD

GCD中有2個(gè)用來(lái)執(zhí)行任務(wù)的函數(shù)

  • 用同步的方式執(zhí)行任務(wù)
    dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
  • 用異步的方式執(zhí)行任務(wù)
    dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

GCD源碼:https://github.com/apple/swift-corelibs-libdispatch

GCD的隊(duì)列

GCD的隊(duì)列可以分為2大類(lèi)型

  • 并發(fā)隊(duì)列(Concurrent Dispatch Queue)
    可以讓多個(gè)任務(wù)并發(fā)執(zhí)行(自動(dòng)開(kāi)啟多個(gè)線程同時(shí)執(zhí)行任務(wù))
    并發(fā)功能只有在異步函數(shù)下才有效
  • 串行隊(duì)列(Serial Dispatch Queue)
    讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行

同步異步主要影響:能不能開(kāi)啟新的線程
同步:在當(dāng)前線程中執(zhí)行任務(wù),不具備開(kāi)啟新線程的能力
異步:在新的線程中執(zhí)行任務(wù),具備開(kāi)啟新線程的能力

并發(fā)串行主要影響:任務(wù)的執(zhí)行方式
并發(fā):多個(gè)任務(wù)并發(fā)執(zhí)行
串行:一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù)

使用sync函數(shù)往當(dāng)前串行隊(duì)列中添加任務(wù),會(huì)卡住當(dāng)前的串行隊(duì)列(產(chǎn)生死鎖)

GCD Group

下面場(chǎng)景如何實(shí)現(xiàn)?

  • 異步并發(fā)執(zhí)行任務(wù)1、任務(wù)2
  • 等任務(wù)1、任務(wù)2都執(zhí)行完畢后,再回到主線程執(zhí)行任務(wù)3
dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
        NSLog(@"Task-1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"Task-2");
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"Task-3");
    });

iOS中的線程同步方案

當(dāng)多個(gè)線程訪問(wèn)同一塊資源時(shí),很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問(wèn)題。
常見(jiàn)的解決方案:使用線程同步技術(shù)。
iOS中,常見(jiàn)的線程鎖有以下幾個(gè):

  • OSSpinLock
  • os_unfair_lock
  • pthread_mutex
  • dispatch_semaphore
  • dispatch_queue(DISPATCH_QUEUE_SERIAL)
  • NSLock
  • NSRecursiveLock
  • NSCondition
  • NSConditionLock
  • @synchronized

OSSpinLock

OSSpinLock叫做”自旋鎖”,等待鎖的線程會(huì)處于忙等(busy-wait)狀態(tài),一直占用著CPU資源
目前已經(jīng)不再安全,可能會(huì)出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題
如果等待鎖的線程優(yōu)先級(jí)較高,它會(huì)一直占用著CPU資源,優(yōu)先級(jí)低的線程就無(wú)法釋放鎖。

os_unfair_lock

os_unfair_lock用于取代不安全的OSSpinLock ,從iOS10開(kāi)始才支持
從底層調(diào)用看,等待os_unfair_lock鎖的線程會(huì)處于休眠狀態(tài),并非忙等
需要導(dǎo)入頭文件#import <os/lock.h>

pthread_mutex

mutex叫做互斥鎖,等待鎖的線程會(huì)處于休眠狀態(tài)
需要導(dǎo)入頭文件#import <pthread.h>

dispatch_semaphore

semaphore叫做”信號(hào)量”
信號(hào)量的初始值,可以用來(lái)控制線程并發(fā)訪問(wèn)的最大數(shù)量
信號(hào)量的初始值為1,代表同時(shí)只允許1條線程訪問(wèn)資源,保證線程同步

@synchronized

@synchronized是對(duì)mutex遞歸鎖的封裝
源碼查看:objc4中的objc-sync.mm文件
@synchronized(obj)內(nèi)部會(huì)生成obj對(duì)應(yīng)的遞歸鎖,然后進(jìn)行加鎖、解鎖操作

iOS線程同步方案性能比較

性能從高到低排序
os_unfair_lock
OSSpinLock
dispatch_semaphore
pthread_mutex
dispatch_queue(DISPATCH_QUEUE_SERIAL)
NSLock
NSCondition
pthread_mutex(recursive)
NSRecursiveLock
NSConditionLock
@synchronized

atomic

-atomic用于保證屬性setter、getter的原子性操作,相當(dāng)于在getter和setter內(nèi)部加了線程同步的鎖
可以參考源碼objc4的objc-accessors.mm
它并不能保證使用屬性的過(guò)程是線程安全的

iOS中的讀寫(xiě)安全方案

  1. pthread_rwlock

等待鎖的線程會(huì)進(jìn)入休眠

  1. dispatch_barrier_async

這個(gè)函數(shù)傳入的并發(fā)隊(duì)列必須是自己通過(guò)dispatch_queue_cretate創(chuàng)建的
如果傳入的是一個(gè)串行或是一個(gè)全局的并發(fā)隊(duì)列,那這個(gè)函數(shù)便等同于dispatch_async函數(shù)的效果

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容