第8章:多線程面試問題——一、GCD;二、NSOperation;三、NSThread;四、多線程與鎖

一、GCD

     1、同步/異步 和 串行/併發

1)、GCD調用的四種組合

    dispatch_sync(serial_queue,^{…}); 同步調用串行隊列

    dispatch_async(serial_queue,^{…});異步調用串行隊列

    dispatch_sync(concurrent_queue,^{…});

    dispatch_async(concurrent_queue,^{…});

2)、dispatch_sync(serial_queue,^{…}); 同步調用串行隊列

     回答出死鎖的6分,還要回答出爲什麼死鎖才能滿分。死鎖原因如下:

3)、dispatch_async(serial_queue,^{…});異步調用串行隊列

     下面代碼不會像同步串行一樣產生死鎖。

4)、dispatch_async(concurrent_queue,^{…});異步併發

     爲什麼printLog函數不執行呢?因爲不管GCD通過哪個隊列執行,最終都會在底層的線程中執行,但是底層線程默認沒有開啓runLoop,所以perform函數不執行。

     2、dispatch_barrier_async

1)、怎樣通過GCD實現多讀單寫?

     dispatch_barrier_async(concurrent_queue,^{//寫操作})

     讀操作爲什麼不用異步呢?因爲讀操作需要立即返回結果。而併發隊列保證了多個線程可以併發執行。

     3、dispatch_group相關知識點

1)、使用GCD實現這個需求?A、B、C三個任務併發,完成後執行任務D?

     我認爲作者的講解是錯的,作者的代碼只能保證block執行完成後開始執行D操作,並不能保證圖片都下載成功後去執行D操作。

 

二、NSOperation

     1、主要優點

a、可以添加任務依賴

b、可以控制任務執行狀態:isReady、isExecuting、isFinished、isCancelled。如果只重寫了main方法,則系統會控制任務執行狀態的變化以及任務的退出。如果重寫了start方法,則需要自行控制任務狀態。

c、可以控制最大併發量

     2、oc源碼說明系統如何控制任務狀態

該處源碼解讀基於gnustep-base-1.24.9版本

     _finish方法的實現如下:

     3、系統怎樣移除一個isFinished=YES的NSOperation的?===網上再搜搜,印證一下!

任務完成後_finish方法通過KVO的方式變更finished狀態爲YES,系通過通過NSOperation Queue來監聽該KVO,然後在合適的時機移除該NSOperation對象。

 

三、NSThread

     NSThread相關的面試問題往往是結合RunLoop來考察的。

     1、NSThread的啓動流程

     2、NSThread實現的常駐線程

比着上圖,只是在爲NSThread指定的selector中啓動RunLoop,如下圖

     3、NSThread的實現機制,即start方法的解讀

該處源碼解讀基於gnustep-base-1.24.9版本。

線程的啓動函數nsthreadLauncher源碼如下:

線程的main函數源碼如下:

start方法開始做了一些異常的判斷,經歷了這些異常判斷之後,在1201行調用pthread_create函數來創建線程,然後在該函數中調用線程的啓動函數nsthreadLauncher,nsthreadLauncher函數中調用線程的main函數,main函數調用創建線程時傳進來的selector,如果要實現常駐線程,則在selector中調起RunLoop。

 

四、多線程與鎖

     1、iOS中有哪些常用鎖?

a、@synchronized:一般在創建單例對象的時候使用。

b、atomic:修飾屬性的關鍵字;對被修飾對象進行原子操作(不負責使用)

c、OSSpinLock:自旋鎖,循環等待訪問,不釋放當前資源==對這個解釋我不理解,再搜搜??用於輕量級數據訪問,如簡單的int值+1/-1操作。

d、NSRecursiveLock:遞歸鎖,特點是可以重入。

e、NSLock:一般用於線程同步。

      這個情況可以通過換成遞歸鎖解決。

f、dispatch_semaphore_t:信號量

     2、dispatch_semaphore_t講解

1)、dispatch_semaphore_t常用函數

     dispatch_semaphore_create(int value)創建數值爲value的信號量;

     dispatch_semaphore_wait(semaphore,time)設置當前線程對信號量的等待時間(如DISPATCH_TIME_FOREVER代表永遠),如果沒有資源則等待;

     dispatch_semaphore_singal(semaphore)釋放信號量的一個值;

2)、dispatch_semaphore_create()函數

     該函數主要用於創建semaphore結構,semaphore結構定義如下:struct semaphore{int value; List<thread>;}其中value是信號量的值,List存儲被阻塞的線程的唯一標識,如pid。

3)、dispatch_semaphore_wait()函數

     函數主要實現如圖,途中第二句代碼的意思是如果信號量的值小於0,則調用該函數的線程主動的將自己阻塞起來。

4)、dispatch_semaphore_singal()函數

     函數主要實現如圖,途中第二句代碼的意思是如果信號量的值小於等於0,則說明有線程處於阻塞狀態,通過wakeup函數去喚醒阻塞的線程。喚醒是一個被動實現。

     3、iOS系統爲我們提供的幾種多線程技術各自的特點是怎樣的?

1)、GCD用來實現一些簡單的線程同步,包括一些子線程的分派,包括實現一些類似於多讀單寫這種場景的問題

2)、NSOperation和NSOperation Queue由於可以控制任務狀態、依賴,所以AFNetwork和SDWebImage內部都使用者兩個類實現多線程。

3)、NSThread常用於實現常駐線程。GCD和NSOperation都不能實現常駐線程,因爲他們底層都是通過系統的線程池執行任務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章