新聞中心
IOS多線程安全(線程鎖)
線程的不安全是由于多線程訪問和修改共享資源而引起的不可預測的結果。
創(chuàng)新互聯(lián)一直通過網(wǎng)站建設和網(wǎng)站營銷幫助企業(yè)獲得更多客戶資源。 以"深度挖掘,量身打造,注重實效"的一站式服務,以做網(wǎng)站、網(wǎng)站制作、移動互聯(lián)產品、營銷型網(wǎng)站建設服務為核心業(yè)務。十載網(wǎng)站制作的經驗,使用新網(wǎng)站建設技術,全新開發(fā)出的標準網(wǎng)站,不但價格便宜而且實用、靈活,特別適合中小公司網(wǎng)站制作。網(wǎng)站管理系統(tǒng)簡單易用,維護方便,您可以完全操作網(wǎng)站資料,是中小公司快速網(wǎng)站建設的選擇。
ios多線程開發(fā)中為保證線程的安全常用到的幾種鎖: NSLock 、 dispatch_semaphore 、 NSCondition 、 NSRecursiveLock 、 @synchronized 。
WEAKSELF typeof(self) __weak weakSelf = self;
NSLock 是OC層封裝底層線程操作來實現(xiàn)的一種鎖,繼承NSLocking協(xié)議。不能迭代加鎖,如果發(fā)生兩次lock,而未unlock過,則會產生死鎖問題。
以車站購票為例,多個窗口同時售票(同步),每個窗口有人循環(huán)購票:
原子操作
原子操作是指不可打斷的操作,也就是說線程在執(zhí)行操作的過程中,不會被操作系統(tǒng)掛起,而是一定會執(zhí)行完,
變量屬性Property中的原子定義
一般我們定義一個變量@property (nonatomic ,strong)NSLock *lock;nonatomic:非原子性,不會為setter方法加鎖,適合內存小的移動設備;atomic:原子性,默認為setter方法加鎖(默認就是atomic),線程安全。
PS: 在iOS開發(fā)過程中,一般都將屬性聲明為nonatomic,盡量避免多線程搶奪同一資源,盡量將加鎖等資源搶奪業(yè)務交給服務器。
NSCondition常用于生產者-消費者模式,它繼承了NSLocking協(xié)議,同樣有l(wèi)ock和unlock方法。條件變量有點像信號量,提供了線程阻塞和信號機制,因此可以用來阻塞某個線程,并等待數(shù)據(jù)就緒再喚醒程序。
信號量主要有3個函數(shù),分別是:
注意: 正常的使用順序是先降低然后提高,這兩個函數(shù)通常都是成對出現(xiàn)。
本文主要參考了這篇文章(
),并對其中所能理解的部分進行一一驗證,以前沒怎么寫過類似的,如果有什么做的不好的地方還請大家多多見諒!
iOS 線程同步
要保證線程安全,就必須要線程同步,而在iOS中線程同步的方案有:
在 iOS 中,原子操作可以保證屬性在單獨的 setter 或者 getter 方法中是線程安全的,但是不能保證多個線程對同一個屬性進行讀寫操作時,可以得到預期的值,也就是原子操作不保證線程安全,例如:
在 Objective-C 中,可以在設置屬性的時候,使用 atomic 來設置原子屬性,保證屬性 setter 、 getter 的原子性操作,底層是在 getter 和 setter 內部使用 os_unfair_lock 加鎖
在 Swift 中,原生沒有提供原子操作,可以使用 DispatchQueue 的同步函數(shù)來達到同樣的效果
pthread 表示 POSIX thread ,是 POSIX 標準的 unix 多線程庫,定義了一組跨平臺的線程相關的API。 pthread_mutex 是一種用 C 語言實現(xiàn)的互斥鎖,有單一的擁有者
遞歸鎖是一種特殊互斥鎖。遞歸鎖允許單個線程在釋放之前多次獲取鎖,其他線程保持睡眠狀態(tài),直到鎖的所有者釋放鎖的次數(shù)與獲取它的次數(shù)相同。遞歸鎖主要在遞歸迭代中使用,但也可能在多個方法需要單獨獲取鎖的情況下使用。
pthread_mutex 支持遞歸鎖,只要把 attr 的類型改成 PTHREAD_MUTEX_RECURSIVE 即可,它有單一的擁有者
NSRecursiveLock 是以 Objective-C 對象的形式對 pthread_mutex(Recursive) 的封裝,它有單一的擁有者
條件鎖是一種特殊互斥鎖,需要條件變量(condition variable) 來配合。條件變量有點像信號量,提供了線程阻塞與信號機制,因此可以用來阻塞某個線程,并等待某個數(shù)據(jù)就緒,隨后喚醒線程。條件鎖是為了解決 生產者-消費者模型
pthread_mutex 配合 pthread_cond_t ,可以實現(xiàn)條件鎖,其中 pthread_cond_t 沒有擁有者
NSCondition 是以 Objective-C 對象的形式對 pthread_mutex 和 pthread_cond_t 進行了封裝, NSCondition 沒有擁有者
NSConditionLock 是對 NSCondition 的進一步封裝,可以設置條件變量的值。通過改變條件變量的值,可以使任務之間產生依賴關系,達到使任務按照一定的順序執(zhí)行,它有單一的擁有者(不確定)
讀寫鎖是一種特殊互斥鎖,提供"多讀單寫"的功能,多個線程可以同時對共享資源進行讀取,但是同一時間只能有一條線程對共享資源進行寫入
pthread_rwlock 有多個擁有者
性能從高到底分別是:
總結:
蘋果官方文檔
白夜追兇,揭開iOS鎖的秘密
起底多線程同步鎖(iOS)
深入理解 iOS 開發(fā)中的鎖
ios 線程與進程
1.進程?
具有一定獨立功能的程序關于某次數(shù)據(jù)集合的一次運行活動,他是操作系統(tǒng)分配資源的基本單位。
進程是指系統(tǒng)正在運行的一個應用程序,就是一段程序的執(zhí)行過程。
各進程之間相互獨立,每個進程都運行在受保護的內存空間內,擁有獨立運行所需的全部資源。
2. 線程
進程的最小執(zhí)行單元。線程是一個進程的實體。
一個進程要想執(zhí)行任務,就必須至少又一個線程,當程序啟動時,系統(tǒng)默認開啟一條線程,也就是主線程。
3、 進程與線程的關系
線程是進程的執(zhí)行單元,進程的所有任務都在線程中執(zhí)行
線程是CPU分配和執(zhí)行任務的最小單元
一個程序可以有多進程,一個進程可以有多線程 ,但是一個進程至少有一個線程
同一個進程內的線程共享進程內的資源
4 多線程原理
同一時間內單核CPU 只執(zhí)行一個線程,多線程是CPU 在單位時間內在多個線程之間切換,造成多個線程被同時執(zhí)行的假象。
多核CPU 就可以執(zhí)行多個線程
多線程的目的是同步執(zhí)行多個線程,來提高運行效率
5、多線程的優(yōu)缺點
有點:提高執(zhí)行效率 能夠提高CPU的使用率
缺點:占用一定的系統(tǒng)內存空間? 線程越多 CPU 調度線程的開銷越大 程序設計復雜(線程之間的通信 數(shù)據(jù)共享)
6、多線程并發(fā) 與并行區(qū)別
并發(fā):在一條線程上快速切換?
并行: 利用多核CPU ,多線程同時進行
7、IOS 中的多線程
NSThread 需要手動創(chuàng)建 不需要銷毀 子線程通信很難
GCD?c語言,充分利用了設備的多核,自動管理線程生命周期。比NSOperation效率更高。
NSOperation??基于gcd封裝,更加面向對象,比gcd多了一些功能。
8、多個網(wǎng)絡請求如何執(zhí)行下一步
使用GCD的dispatch_group_t??
創(chuàng)建一個dispatch_group_t
每次網(wǎng)絡請求前先dispatch_group_enter,請求回調后再dispatch_group_leave,enter和leave必須配合使用,有幾次enter就要有幾次leave,否則group會一直存在。
當所有enter的block都leave后,會執(zhí)行dispatch_group_notify的block。
NSString *str = @"";
NSURL*url = [NSURLURLWithString:str];
NSURLRequest*request = [NSURLRequestrequestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
dispatch_group_tdownloadGroup =dispatch_group_create();
for ( int i=0; i10; i++) {
? ? dispatch_group_enter(downloadGroup);
? ? NSURLSessionDataTask*task = [sessiondataTaskWithRequest:requestcompletionHandler:^(NSData* _Nullable data,NSURLResponse* _Nullable response,NSError* _Nullable error) {
? ? ? ? NSLog(@"%d---%d",i,i);
? ? ? ? dispatch_group_leave(downloadGroup);
? ? }];
? ? [taskresume];
}
dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
? ? NSLog(@"end");
});
7.多個網(wǎng)絡請求順序執(zhí)行后如何執(zhí)行下一步?
使用信號量semaphore
每一次遍歷,都讓其dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER),這個時候線程會等待,阻塞當前線程,直到dispatch_semaphore_signal(sem)調用之后
NSString*str=@"";
NSURL*url=[NSURL URLWithString:str];
NSURLRequest*request=[NSURLRequest requestWithURL:url];
NSURLSession*session=[NSURLSession sharedSession];
dispatch_semaphore_t sem=dispatch_semaphore_create(0);
for(inti=0;i10;i++){
NSURLSessionDataTask*task=[session dataTaskWithRequest:request completionHandler:^(NSData*_Nullable data,NSURLResponse*_Nullable response,NSError*_Nullable error){
NSLog(@"%d---%d",i,i);
dispatch_semaphore_signal(sem);
}];
[task resume];
dispatch_semaphore_wait(sem,DISPATCH_TIME_FOREVER);
}
dispatch_async(dispatch_get_main_queue(),^{
NSLog(@"end");
});
iOS-線程與進程簡介
線程和進程在我們開發(fā)中,跟我們一直形影不離,那么什么是進程,什么是線程,它們又有什么關系,這篇文章將為您簡單介紹。
線程概念
進程概念
地址空間:同?進程的線程共享本進程的地址空間( TLS是本地的線程棧存空間,線程的局部空間是某些操作系統(tǒng)為線程提供的私有空間,只具備有限的容量,并不屬于線程,由操作系統(tǒng)單獨安排的 ),?進程之間則是獨?的地址空間。
資源擁有:同?進程內的線程共享本進程的資源如內存、I/O、cpu等,但是進程之間的資源是獨?的。
優(yōu)點:
缺點:
時間?的概念:CPU在多個任務直接進?快速的切換,這個時間間隔就是時間?。
多線程同時執(zhí)行
如果線程非常多
互斥鎖?結
互斥鎖參數(shù)
nonatomic?原?屬性
atomic原?屬性(線程安全),針對多線程設計的,默認值,保證同?時間只有?個線程能夠寫?(但是同?個時間多個線程都可以取值)
atomic本身就有?把鎖(?旋鎖)
單寫多讀:單個線程寫?,多個線程可以讀取
atomic:線程安全,需要消耗?量的資源
nonatomic:?線程安全,適合內存?的移動設備
iOS開發(fā)建議
所有屬性都聲明為nonatomic
盡量避免多線程搶奪同一塊資源
盡量將加鎖,資源搶奪的業(yè)務邏輯交給服務器處理,減少APP的壓力
這篇文章簡單介紹了線程與進程的概念,煩請大家不吝賜教。
NSOperation'>iOS多線程GCD任務取消->NSOperation
在多線程開發(fā)中,我們常用到GCD,這里探討一下GCD任務的取消:
1.在iOS 8以后,系統(tǒng)給我們提供了這樣的取消函數(shù) dispatch_block_cancel,不過這個也只能用于dispatch_block_create創(chuàng)建的dispatch_block_t,我們試驗一下:
這時肯定是任務都會執(zhí)行的
接下來,把注釋的那一行 dispatch_block_cancel(block1);打開,看看效果:
我們發(fā)現(xiàn)block1確實被取消掉了。這是dispatch_block_cancel的用法。
2.很多時候,我們的場景不會去用dispatch_block_create創(chuàng)建dispatch_block_t,這個時候我們若想取消一個任務,可以考慮用一個條件來做,滿足條件則執(zhí)行此任務,不滿足則不執(zhí)行,舉個例子:
效果如下:
寫到這里,這兒其實還隱藏了一個知識點,就是block的變量捕獲,有興趣或是不理解的朋友可以研究一下。(如下,為何輸出不是20而是10)
3.過渡到NSOperation
NSOperation是對GCD的封裝,底層也是GCD。
NSOperation給我們封裝了更多的api,這是我在Xcode中提出來的:
我們可以發(fā)現(xiàn)它有狀態(tài)屬性,有取消方法,也有添加依賴方法等...這里我們還是先說取消吧,下面來給大家寫個demo:
這時輸出是:
因為正在執(zhí)行的任務,NSOperation也是不能取消的,所以也是需要將cancel在start前調用的(就如同滿足一個條件是否需要cancel一樣,也可以滿足條件不調用start)
文章題目:ios開發(fā)多線程,ios開發(fā)多線程面試題
文章位置:http://www.dlmjj.cn/article/dsejpgj.html