iOS開發(fā)中多線程的安全隱患總結(jié)
資源共享
1塊資源可能會(huì)被多個(gè)線程共享,也就是多個(gè)線程可能會(huì)訪問同一塊資源
比如多個(gè)線程訪問同一個(gè)對(duì)象、同一個(gè)變量、同一個(gè)文件
當(dāng)多個(gè)線程訪問同一塊資源時(shí),很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問題
一、解決方案
解決方案:使用線程同步技術(shù)(同步,就是協(xié)同步調(diào),按預(yù)定的先后次序進(jìn)行)
常見的線程同步技術(shù)是:加鎖
1、OSSpinLock
OSSpinLock叫做”自旋鎖”,等待鎖的線程會(huì)處于忙等(busy-wait)狀態(tài),一直占用著CPU資源
目前已經(jīng)不再安全,可能會(huì)出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn)問題
如果等待鎖的線程優(yōu)先級(jí)較高,它會(huì)一直占用著CPU資源,優(yōu)先級(jí)低的線程就無法釋放鎖
需要導(dǎo)入頭文件#import<libkern/OSAtomic.h>
2、os_unfair_lock
os_unfair_lock用于取代不安全的OSSpinLock,從iOS10開始才支持
從底層調(diào)用看,等待os_unfair_lock鎖的線程會(huì)處于休眠狀態(tài),并非忙等
需要導(dǎo)入頭文件#import<os/lock.h>
3、pthread_mutex
mutex叫做”互斥鎖”,等待鎖的線程會(huì)處于休眠狀態(tài)
需要導(dǎo)入頭文件#import<pthread.h>
pthread_mutex–普通鎖
pthread_mutex–遞歸鎖
pthread_mutex–條件
4、NSLock
NSLock是對(duì)mutex普通鎖的封裝
5、NSRecursiveLock
NSRecursiveLock也是對(duì)mutex遞歸鎖的封裝,API跟NSLock基本一致
6、NSCondition
NSCondition是對(duì)mutex和cond的封裝
7、NSConditionLock
NSConditionLock是對(duì)NSCondition的進(jìn)一步封裝,可以設(shè)置具體的條件值
8、dispatch_semaphore
semaphore叫做”信號(hào)量”
信號(hào)量的初始值,可以用來控制線程并發(fā)訪問的最大數(shù)量
信號(hào)量的初始值為1,代表同時(shí)只允許1條線程訪問資源,保證線程同步
9、dispatch_queue(DISPATCH_QUEUE_SERIAL)
直接使用GCD的串行隊(duì)列,也是可以實(shí)現(xiàn)線程同步的
10、@synchronized
@synchronized是對(duì)mutex遞歸鎖的封裝
源碼查看:objc4中的objc-sync.mm文件(蘋果源碼官方地址)
@synchronized(obj)內(nèi)部會(huì)生成obj對(duì)應(yīng)的遞歸鎖,然后進(jìn)行加鎖、解鎖操作
二、iOS線程同步方案性能比較
原則:
普通鎖比遞歸鎖性能好
語言越高級(jí),封裝的邏輯越多,性能也就越差(所有語言都如此)
實(shí)際測(cè)試
性能從高到低排序
os_unfair_lock // 缺點(diǎn):iOS10才支持
OSSpinLock // 缺點(diǎn):可能出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn) 已經(jīng)不再安全 蘋果也不推薦使用
dispatch_semaphore // 推薦使用
pthread_mutex // 優(yōu)點(diǎn):跨平臺(tái) 互斥鎖(普通鎖) 推薦使用
dispatch_queue(DISPATCH_QUEUE_SERIAL) // c
NSLock // oc
NSCondition // oc
pthread_mutex(recursive) // 遞歸鎖
NSRecursiveLock // oc
NSConditionLock // oc
@synchronized // 遞歸鎖 oc
三、自旋鎖、互斥鎖 選擇
自旋鎖:等待狀態(tài)處于忙等
互斥鎖:等待狀態(tài)處于休眠
1、什么情況使用自旋鎖比較劃算?
預(yù)計(jì)線程等待鎖的時(shí)間很短
加鎖的代碼(臨界區(qū))經(jīng)常被調(diào)用,但競(jìng)爭(zhēng)情況很少發(fā)生
CPU資源不緊張
多核處理器
2、什么情況使用互斥鎖比較劃算?
預(yù)計(jì)線程等待鎖的時(shí)間較長(zhǎng)
單核處理器
臨界區(qū)有IO操作
臨界區(qū)代碼復(fù)雜或者循環(huán)量大
臨界區(qū)競(jìng)爭(zhēng)非常激烈
四、讀寫鎖
場(chǎng)景:
同一時(shí)間,只能有1個(gè)線程進(jìn)行寫的操作
同一時(shí)間,允許有多個(gè)線程進(jìn)行讀的操作
同一時(shí)間,不允許既有寫的操作,又有讀的操作
上面的場(chǎng)景就是典型的“多讀單寫”,經(jīng)常用于文件等數(shù)據(jù)的讀寫操作,iOS中的實(shí)現(xiàn)方案有:
1、讀寫鎖:pthread_rwlock
等待鎖的線程會(huì)進(jìn)入休眠
2、dispatch_barrier_async
這個(gè)函數(shù)傳入的并發(fā)隊(duì)列必須是自己通過dispatch_queue_cretate創(chuàng)建的
如果傳入的是一個(gè)串行或是一個(gè)全局的并發(fā)隊(duì)列,那這個(gè)函數(shù)便等同于dispatch_async函數(shù)的效果
相關(guān)文章
解決iOS11刷新tableview會(huì)出現(xiàn)漂移的現(xiàn)象
這篇文章主要介紹了解決iOS11刷新tableview會(huì)出現(xiàn)漂移的現(xiàn)象,需要的朋友可以參考下2017-10-10使用objc runtime實(shí)現(xiàn)iOS閉環(huán)的懶加載功能
利用objc runtime的動(dòng)態(tài)性實(shí)現(xiàn)懶加載可以實(shí)現(xiàn)即可增加又可刪除功能,也可以避免污染類型。這篇文章主要介紹了使用objc runtime實(shí)現(xiàn)iOS閉環(huán)的懶加載功能,需要的朋友可以參考下2019-06-06iOS安全防護(hù)系列之字符串及系統(tǒng)函數(shù)隱藏詳解
這篇文章主要給大家介紹了關(guān)于iOS安全防護(hù)系列之字符串及系統(tǒng)函數(shù)隱藏的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07iOS框架AVFoundation實(shí)現(xiàn)相機(jī)拍照、錄制視頻
這篇文章主要為大家詳細(xì)介紹了iOS框架AVFoundation實(shí)現(xiàn)相機(jī)拍照、錄制視頻功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05iOS用AutoLayout實(shí)現(xiàn)分頁滾動(dòng)功能
這篇文章主要給大家介紹了關(guān)于iOS用AutoLayout實(shí)現(xiàn)分頁滾動(dòng)功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位iOS開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06iOS使用UICountingLabel實(shí)現(xiàn)數(shù)字變化的動(dòng)畫效果
本文主要介紹了iOS使用UICountingLabel實(shí)現(xiàn)數(shù)字變化動(dòng)畫效果的方法,具有一定的參考價(jià)值,下面跟著小編一起來看下吧2016-12-12Flutter?GetPageRoute實(shí)現(xiàn)嵌套導(dǎo)航學(xué)習(xí)
這篇文章主要為大家介紹了Flutter?GetPageRoute實(shí)現(xiàn)嵌套導(dǎo)航的示例學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08