iOS開發——高級篇——多線程的安全隱患


資源共享
1塊資源可能會被多個線程共享,也就是多個線程可能會訪問同一塊資源
比如多個線程訪問同一個對象、同一個變量、同一個文件

 

當多個線程訪問同一塊資源時,很容易引發 數據錯亂和數據安全問題
 
一、解決方案
解決方案:使用線程同步技術(同步,就是協同步調,按預定的先后次序進行)
常見的線程同步技術是:加鎖
 
1、OSSpinLock
OSSpinLock叫做”自旋鎖”,等待鎖的線程會處於忙等(busy-wait)狀態,一直占用着CPU資源
目前已經不再安全,可能會出現優先級反轉問題
如果等待鎖的線程優先級較高,它會一直占用着CPU資源,優先級低的線程就無法釋放鎖
需要導入頭文件#import<libkern/OSAtomic.h>
 

 

2、os_unfair_lock
os_unfair_lock用於取代不安全的OSSpinLock,從iOS10開始才支持
從底層調用看,等待os_unfair_lock鎖的線程會處於休眠狀態,並非忙等
需要導入頭文件#import<os/lock.h>

 

 
3、pthread_mutex
mutex叫做”互斥鎖”,等待鎖的線程會處於休眠狀態
需要導入頭文件#import<pthread.h>
 
pthread_mutex–普通鎖

 

 
pthread_mutex–遞歸鎖
 
pthread_mutex–條件

 

 
4、NSLock
NSLock是對mutex普通鎖的封裝

 

 
5、NSRecursiveLock

NSRecursiveLock也是對mutex遞歸鎖的封裝,API跟NSLock基本一致

 

6、NSCondition
NSCondition是對mutex和cond的封裝

 

7、NSConditionLock
NSConditionLock是對NSCondition的進一步封裝,可以設置具體的條件值

 

8、dispatch_semaphore
semaphore叫做”信號量”
信號量的初始值,可以用來控制線程並發訪問的最大數量
信號量的初始值為1,代表同時只允許1條線程訪問資源,保證線程同步

 

  
9、dispatch_queue(DISPATCH_QUEUE_SERIAL)
 直接使用GCD的串行隊列,也是可以實現線程同步的

 

 
10、@synchronized
@synchronized是對mutex遞歸鎖的封裝
源碼查看:objc4中的objc-sync.mm文件( 蘋果源碼官方地址)
@synchronized(obj)內部會生成obj對應的遞歸鎖,然后進行加鎖、解鎖操作

 

二、iOS線程同步方案性能比較
原則:
  普通鎖比遞歸鎖性能好
  語言越高級,封裝的邏輯越多,性能也就越差(所有語言都如此) 
  實際測試
 
性能從高到低排序
os_unfair_lock   // 缺點:iOS10才支持  
OSSpinLock  // 缺點:可能出現優先級反轉 已經不再安全 蘋果也不推薦使用
dispatch_semaphore // 推薦使用 
pthread_mutex  // 優點:跨平台 互斥鎖(普通鎖) 推薦使用
dispatch_queue(DISPATCH_QUEUE_SERIAL) // c
NSLock     // oc
NSCondition   // oc
pthread_mutex(recursive) // 遞歸鎖
NSRecursiveLock  // oc
NSConditionLock   // oc
@synchronized // 遞歸鎖 oc

 

三、自旋鎖、互斥鎖 選擇
自旋鎖:等待狀態處於忙等
互斥鎖:等待狀態處於休眠
 
1、什么情況使用自旋鎖比較划算?
預計線程等待鎖的時間很短
加鎖的代碼(臨界區)經常被調用,但競爭情況很少發生
CPU資源不緊張
多核處理器
 
2、什么情況使用互斥鎖比較划算?
預計線程等待鎖的時間較長
單核處理器
臨界區有IO操作
臨界區代碼復雜或者循環量大
臨界區競爭非常激烈

 

四、讀寫鎖 
 場景:
同一時間,只能有1個線程進行寫的操作
同一時間,允許有多個線程進行讀的操作
同一時間,不允許既有寫的操作,又有讀的操作
 
 上面的場景就是典型的“多讀單寫”,經常用於文件等數據的讀寫操作,iOS中的實現方案有:
1、讀寫鎖: pthread_rwlock

等待鎖的線程會進入休眠

 

 

2、dispatch_barrier_async

這個函數傳入的並發隊列必須是自己通過dispatch_queue_cretate創建的

如果傳入的是一個串行或是一個全局的並發隊列,那這個函數便等同於dispatch_async函數的效果

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM