多線程與線程安全

1.線程安全的維度

1.線程間安全,不會產(chǎn)生線程死鎖、由線程操作產(chǎn)生的異常崩潰
2.線程數(shù)據(jù)安全,對于同時可讀可寫的數(shù)據(jù),需要有同步操作

2. 看一個多個線程同時讀寫操作一個變量的例子

@property (nonatomic,strong)NSString *target;

// queue 是并發(fā)對壘
for (int  index = 0; index < 1000; index++) {
        dispatch_async(queue, ^{
            //如果是并行隊(duì)列里邊 改變同一塊內(nèi)存要加鎖
            self.target = [NSString stringWithFormat:@"ksddkjalkjd%d",index];
            NSLog(@"%@",self.target);
        });
 }

這段代碼存在的問題

1.target 打印的數(shù)據(jù)有肯能不是按順序的,也就是說數(shù)據(jù)會錯亂
2.程序崩潰. 原因:

在iOS中 一個變量在獲取新值之前要釋放以前的舊址
在并行訪問同一塊資源的時候 如果釋放了一次舊址 再次釋放就會導(dǎo)致過度釋放
過度釋放會讓程序崩潰 報BAD_ACCESS_ADDRESS

這類問題我們需要用線程同步來處理,線程同步常用方法有:

  1. 互斥鎖和讀寫鎖:提供對臨界資源的保護(hù),當(dāng)多線程試圖訪問臨界資源時,都必須通過獲取鎖的方式來訪問臨界資源。(臨界資源:是被多線程共享的資源)當(dāng)讀寫線程獲取鎖的頻率差別不大時,一般采用互斥鎖,如果讀線程訪問臨界資源的頻率大于寫線程,這個時候采用讀寫鎖較為合適,讀寫鎖允許多個讀線程同時訪問臨界資源,讀寫線程必須互斥訪問臨界資源。讀寫鎖的實(shí)現(xiàn)采用了互斥鎖,所以在讀寫次數(shù)差不多的情況下采用讀寫鎖性能沒有直接采用互斥鎖來的高。
  2. 條件變量:提供線程之間的一種通知機(jī)制,當(dāng)某一條件滿足時,線程A可以通知阻塞在條件變量上的線程B,B所期望的條件已經(jīng)滿足,可以解除在條件變量上的阻塞操作,繼續(xù)做其他事情。
  3. 信號量:提供對臨界資源的安全分配。如果存在多份臨界資源,在多個線程爭搶臨界資源的情況下,向線程提供安全分配臨界資源的方法。如果臨界資源的數(shù)量為1,將退化為鎖。
  4. 令牌:一種高級的線程同步的方法。它既提供鎖的安全訪問臨界資源的功能,又利用了條件變量使得線程爭奪臨界資源時是有序的。

3.線程同步導(dǎo)致死鎖

例如: 1.線程循環(huán)等待導(dǎo)致死鎖

//當(dāng)前是主隊(duì)列
dispatch_sync(dispatch_get_main_queue(), ^{
            
 });
 // 如果是非主隊(duì)列也如此
dispatch_queue_t queue = dispatch_queue_create("gcd", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{
  NSLog(@"外邊的1 %@",[NSThread currentThread]);
  dispatch_sync(queue, ^{
      NSLog(@"里邊的 %@",[NSThread currentThread]);
            
        });
      NSLog(@"外邊的2 %@",[NSThread currentThread]);
        
});

2.線程同步時資源競爭

例如 下圖左右兩個線程要使用獨(dú)立的兩個資源A和B,而且只有在代碼塊結(jié)束后才讓別的線程使用A、B兩種資源,當(dāng)A和B分別被這兩個線程得到后,在執(zhí)行1和2兩步后,線程會死鎖,一直等待他們需要的資源
線程會死鎖

解決方法

1.資源的加鎖范圍盡量縮小,也就是可以不占用后立馬釋放
2.加鎖時限(線程嘗試獲取鎖的時候加上一定的時限,超過時限則放棄對該鎖的請求,并釋放自己占有的鎖)

  1. 死鎖檢測是一個更好的死鎖預(yù)防機(jī)制,它主要是針對那些不可能實(shí)現(xiàn)按序加鎖并且鎖超時也不可行的場景。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 在上篇中,我們已經(jīng)討論過如何去實(shí)現(xiàn)一個 Map 了,并且也討論了諸多優(yōu)化點(diǎn)。在下篇中,我們將繼續(xù)討論如何實(shí)現(xiàn)一個線...
    一縷殤流化隱半邊冰霜閱讀 7,847評論 5 41
  • 線程池ThreadPoolExecutor corepoolsize:核心池的大小,默認(rèn)情況下,在創(chuàng)建了線程池之后...
    irckwk1閱讀 863評論 0 0
  • 1. 進(jìn)程、線程、任務(wù) 進(jìn)程(process),指的是一個正在運(yùn)行中的可執(zhí)行文件。每一個進(jìn)程都擁有獨(dú)立的虛擬內(nèi)存空...
    毅個天亮閱讀 294評論 0 0
  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來是分開三篇的,后來想想還是整...
    coder_pig閱讀 1,760評論 2 17
  • 我想了想,還是想見你一面,哪怕一眼也好。 2017年8月14日 星期一 多云轉(zhuǎn)晴 隨風(fēng)搖曳的一串燭光,近了,遠(yuǎn)了,...
    花見川閱讀 335評論 0 3

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