iOS開發(fā)常問點:GCD實現(xiàn)多讀單寫

比如在內(nèi)存中維護(hù)一份數(shù)據(jù),有多處地方可能會同時操作這塊數(shù)據(jù),怎么能保證數(shù)據(jù)安全?這道題目總結(jié)得到要滿足以下三點:

  • 1.讀寫互斥
  • 2.寫寫互斥
  • 3.讀讀并發(fā)
@implementation KCPerson
- (instancetype)init
{
    if (self = [super init]) {
       _concurrentQueue = dispatch_queue_create("com.kc_person.syncQueue", DISPATCH_QUEUE_CONCURRENT);
       _dic = [NSMutableDictionary dictionary];
    }
    return self;
}
- (void)kc_setSafeObject:(id)object forKey:(NSString *)key{
    key = [key copy];
    dispatch_barrier_async(_concurrentQueue, ^{
       [_dic setObject:object key:key];
    });
}
- (id)kc_safeObjectForKey::(NSString *)key{
    __block NSString *temp;
    dispatch_sync(_concurrentQueue, ^{
        temp =[_dic objectForKey:key];
    });
    return temp;
}
@end
  • 首先我們要維系一個GCD 隊列,最好不用全局隊列,畢竟大家都知道全局隊列遇到柵欄函數(shù)是有坑點的,這里就不分析了!

  • 因為考慮性能 死鎖 堵塞的因素不考慮串行隊列,用的是自定義的并發(fā)隊列!
    _concurrentQueue = dispatch_queue_create("com.kc_person.syncQueue", DISPATCH_QUEUE_CONCURRENT);

  • 首先我們來看看讀操作:kc_safeObjectForKey我們考慮到多線程影響是不能用異步函數(shù)的!說明:

    • 線程2 獲取:name 線程3 獲取 age
    • 如果因為異步并發(fā),導(dǎo)致混亂 本來讀的是name 結(jié)果讀到了age
    • 我們允許多個任務(wù)同時進(jìn)去! 但是讀操作需要同步返回,所以我們選擇:同步函數(shù)(讀讀并發(fā))
  • 我們再來看看寫操作,在寫操作的時候?qū)ey進(jìn)行了copy, 關(guān)于此處的解釋,插入一段來自參考文獻(xiàn)的引用:

函數(shù)調(diào)用者可以自由傳遞一個NSMutableStringkey,并且能夠在函數(shù)返回后修改它。因此我們必須對傳入的字符串使用copy操作以確保函數(shù)能夠正確地工作。如果傳入的字符串不是可變的(也就是正常的NSString類型),調(diào)用copy基本上是個空操作。

  • 這里我們選擇dispatch_barrier_async, 為什么是柵欄函數(shù)而不是異步函數(shù)或者同步函數(shù),下面分析:
    • 柵欄函數(shù)任務(wù):之前所有的任務(wù)執(zhí)行完畢,并且在它后面的任務(wù)開始之前,期間不會有其他的任務(wù)執(zhí)行,這樣比較好的促使 寫操作一個接一個寫 (寫寫互斥),不會亂!
    • 為什么不是異步函數(shù)?應(yīng)該很容易分析,畢竟會產(chǎn)生混亂!
    • 為什么不用同步函數(shù)?如果讀寫都操作了,那么用同步函數(shù),就有可能存在:我寫需要等待讀操作回來才能執(zhí)行,顯然這里是不合理!

閱讀更多:

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

相關(guān)閱讀更多精彩內(nèi)容

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