總結(jié):
1.進(jìn)程和線程
進(jìn)程是系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序,活動監(jiān)視器可以看到。
線程是CPU執(zhí)行任務(wù)的最小單元。
進(jìn)程是CPU分配資源的最小單元。
一個(gè)應(yīng)用程序運(yùn)行至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程中至少有一個(gè)主線程。
2.iOS 中的線程 應(yīng)用
pthread NSThread GCD NSOpreation
1.pthread:
pthread_create(&threadId, NULL, &demo, (__bridge void *)(str));
2.NSThread- 寫常駐線程。
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"jack"];
[self performSelectorInBackground:@selector(run:) withObject:@"jack"];
2.1
NSThread start()方法源碼里面會啟動一個(gè)nsthreadLauncher方法
[t main];
[NSThread exit];
- (void) main
{
略。。。
[_target performSelector: _selector withObject: _arg];
}
所以要把常駐線程寫在selector里面,子線程的runloop 默認(rèn)是停止的。

2.2sched_yield :sched_yield()這個(gè)函數(shù)可以使用另一個(gè)級別等于或高于當(dāng)前線程的線程先運(yùn)行。如果沒有符合條件的線程,那么這個(gè)函數(shù)將會立刻返回然后繼續(xù)執(zhí)行當(dāng)前線程的程序.
2.3線程死了之后就不能被開啟。
2.4[NSThread sleepForTimeInterval:2.0]; 阻塞
2.5 cancel finished.
如果剛開始就被cancel了 線程中的任務(wù)沒有執(zhí)行,所以就不會執(zhí)行。
如果任務(wù)開始了,cancel 這個(gè)線程,任務(wù)不會停止,直到執(zhí)行完。
exit可以停止線程。殺掉主線程,但app不會掛掉,后面的代碼不會執(zhí)行。


3.GCD:
任務(wù)的執(zhí)行方式:同步任務(wù),異步任務(wù),
隊(duì)列的調(diào)度:隊(duì)列是用來調(diào)度任務(wù)的,串行,并發(fā)。
3.1dispatch_async(queue,block) async 異步隊(duì)列,dispatch_async 函數(shù)會立即返回, block會在后臺異步執(zhí)行。
dispatch_sync(queue,block) sync 同步隊(duì)列,dispatch_sync 函數(shù)不會立即返回,及阻塞當(dāng)前線程,等待 block同步執(zhí)行完成。
dispatch_sync(dispatch_get_main_queue() ^{
});
主隊(duì)列 會在主線程執(zhí)行

同步主隊(duì)列
同步串行隊(duì)列
同步并行
異步主隊(duì)列
異步串行
dispatch_queue_t q = dispatch_queue_create("tanzhouios", NULL);
異步并行
dispatch_queue_t q = dispatch_queue_create("tanzhou", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(q, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
});
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
有一個(gè)互斥鎖。
dispatch_once(&onceToken, ^{
//只會執(zhí)行一次!!
NSLog(@"執(zhí)行了%@",[NSThread currentThread]);
});
GCD延時(shí)執(zhí)行:
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
dispatch_after(when, dispatch_queue_create("tanzhou", NULL), ^{
NSLog(@"%@",[NSThread currentThread]);
});
異步組:
dispatch_group_async()
柵欄-多讀單寫。
dispatch_barrier_async()
-
NSOperation 是一個(gè)抽象類,不具備操作的能力,必須使用他的子類。
NSInvacationOperation
NSBlockOperation
添加任務(wù)依賴:
任務(wù)執(zhí)行狀態(tài)控制:
4.1
start()自行控制任務(wù)狀態(tài)。執(zhí)行狀態(tài)。
start (){
main()底層控制變更任務(wù)執(zhí)行完成狀態(tài),以及任務(wù)退出。
}
狀態(tài)改變-KVO的方式:
系統(tǒng)怎么移除一個(gè)isFinished = YES 的NSOperation的?
答案:通過KVO.的方式。4.2 最大并發(fā)數(shù)
最大并發(fā)數(shù)量如果是2 會保持最多有兩個(gè)線程在執(zhí)行,線程沒有任務(wù)會被回收,重新創(chuàng)建線程
4.3 暫停&恢復(fù)
如果隊(duì)列被掛起,就不在隊(duì)列里面拿操作了。
如果掛起隊(duì)列的時(shí)候,正在執(zhí)行的任務(wù)不會暫停。
隊(duì)列的 cancelAll
隊(duì)列的 isSuspended 暫停 繼續(xù)。
[op2 addDependency:op1];//op2 依賴于 op1 == op1 執(zhí)行完畢 op2 開始執(zhí)行
[op3 addDependency:op2];
// !!千萬注意!!!: 不要循環(huán)依賴!!!!,一旦指定了循環(huán)依賴,隊(duì)列就不能執(zhí)行被循環(huán)依賴的操作了!!
//不會造成死鎖! 但是 以前的版本 會死鎖!!

5.鎖:
自旋鎖:
OSSpinLock 自旋鎖(雖然已經(jīng)被證明不安全 優(yōu)先級翻轉(zhuǎn)),性能最高的鎖。原理很簡單,就是一直 do while 忙等。它的缺點(diǎn)是當(dāng)?shù)却龝r(shí)會消耗大量 CPU 資源,所以它不適用于較長時(shí)間的任務(wù)。對于內(nèi)存緩存的存取來說,它非常合適。
自旋鎖。循環(huán)等待訪問,不釋放資源。
具體來說,如果一個(gè)低優(yōu)先級的線程獲得鎖并訪問共享資源,這時(shí)一個(gè)高優(yōu)先級的線程也嘗試獲得這個(gè)鎖,它會處于 spin lock 的忙等狀態(tài)從而占用大量 CPU。此時(shí)低優(yōu)先級線程無法與高優(yōu)先級線程爭奪 CPU 時(shí)間,從而導(dǎo)致任務(wù)遲遲完不成、無法釋放 lock。這并不只是理論上的問題,libobjc 已經(jīng)遇到了很多次這個(gè)問題了,于是蘋果的工程師停用了 OSSpinLock。主要原因發(fā)生在低優(yōu)先級線程拿到鎖時(shí),高優(yōu)先級線程進(jìn)入忙等(busy-wait)狀態(tài),消耗大量 CPU 時(shí)間,從而導(dǎo)致低優(yōu)先級線程拿不到 CPU 時(shí)間,也就無法完成任務(wù)并釋放鎖。這種問題被稱為優(yōu)先級反轉(zhuǎn)
互斥鎖:如果共享數(shù)據(jù)已經(jīng)有其他線程加鎖了,線程會進(jìn)入休眠狀態(tài)等待鎖。一旦被訪問的資源被解鎖,則等待資源的線程會被喚醒。
自旋鎖:如果共享數(shù)據(jù)已經(jīng)有其他線程加鎖了,線程會以死循環(huán)的方式等待鎖,一旦被訪問的資源被解鎖,則等待資源的線程會立即執(zhí)行。
自旋鎖的效率高于互斥鎖。
查看 CoreFoundation 的源碼能夠發(fā)現(xiàn),蘋果至少在 2014 年就發(fā)現(xiàn)了這個(gè)問題,并把CoreFoundation 中的 spinlock 替換成了 pthread_mutex。
信號量
pthread_mutex 不是使用忙等,而是阻塞線程并睡眠.
信號量:
dispatch_semaphore_create(信號量值)
//等待降低信號量
dispatch_semaphore_wait
//提高信號量
dispatch_semaphore_signal
假設(shè)現(xiàn)在系統(tǒng)有兩個(gè)空閑資源可以被利用,但同一時(shí)間卻有三個(gè)線程要進(jìn)行訪問,這種情況下,該如何處理呢?
或者
我們要下載很多圖片,并發(fā)異步進(jìn)行,每個(gè)下載都會開辟一個(gè)新線程,可是我們又擔(dān)心太多線程肯定cpu吃不消,那么我們這里也可以用信號量控制一下最大開辟線程數(shù)。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
1.dispatch_semaphore_create:創(chuàng)建一個(gè)Semaphore并初始化信號的總量
2.dispatch_semaphore_signal:發(fā)送一個(gè)信號,讓信號總量加1
3.dispatch_semaphore_wait:可以使總信號量減1,當(dāng)信號總量為0時(shí)就會一直等待(阻塞所在線程),否則就可以正常執(zhí)行。類似于停車位。

遞歸鎖:
NSRecursiveLock 遞歸鎖。重入
NSLock:[lock. lock];[lock. unlock];
方法再一個(gè) [lock. lock];[lock. unlock];會重入,
@synchronized 單列對象時(shí)候使用。保證對象是唯一的。
Atomic: nsmutableArray 付給值是安全的。但是添加和操作這個(gè)array是不安全的。