線程總結(jié)篇:

總結(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)是停止的。


屏幕快照 2019-03-06 下午4.18.30.png

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í)行。

20FAA9A4B4511980353E61A405C6F930.png
12036E02AE31A2A5870520A61EE148CC.png

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í)行


D6677A40-E963-4182-9473-4373F9A7228E.png

同步主隊(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()

  1. 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)依賴的操作了!!
//不會造成死鎖! 但是 以前的版本 會死鎖!!


B4D654897641F2D59455D5A2B073E7CD.png

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í)行。類似于停車位。


9A7D86E63C8104F611710D50213454DE.png

遞歸鎖:
NSRecursiveLock 遞歸鎖。重入
NSLock:[lock. lock];[lock. unlock];
方法再一個(gè) [lock. lock];[lock. unlock];會重入,

@synchronized 單列對象時(shí)候使用。保證對象是唯一的。

Atomic: nsmutableArray 付給值是安全的。但是添加和操作這個(gè)array是不安全的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 娟 是一個(gè)特別愛鬧騰 特別愛笑的一個(gè)女孩 跟她在一起特別開心 沒有煩惱 仿佛每根神經(jīng)都在放松 她總是把我?guī)г?..
    李飛啊閱讀 362評論 0 0
  • 銀色的沙灘, 皎潔的月光, 手牽著手, 光著腳丫, 留下腳印一串串。 你儂我儂, 天長地久, 陪你到天涯海角, 陪...
    誰能任性不認(rèn)命_572a閱讀 210評論 3 11
  • 新年的爆竹尚未落幕 手機(jī)里傳來了朋友的祝福 情人節(jié)快樂 快樂情人節(jié) ...
    孤谷寞陌閱讀 278評論 0 0
  • 1,從本篇文章中學(xué)到了重要的概念; 一篇文章,首先整體的不受干擾的看一遍,然后再多次閱讀(包括把不會的反復(fù)看。查)...
    蘿卜學(xué)者閱讀 155評論 1 0
  • 親愛的(七年后的自己),還記得咱們勾搭上的日子嗎? 我想你一定和我一樣不會忘記:2018年2月14日這個(gè)情人節(jié)!這...
    娟娟呀閱讀 1,417評論 3 5

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