iOS中的鎖和線程同步

線程同步和iOS中的鎖
一、自旋鎖(OSSpinLock)

  1. 一直占用cpu,相當于while循環(huán)
  2. 已經不被推薦,因為可能會產生優(yōu)先級反轉;

優(yōu)先級反轉

  1. 多任務的調度有許多算法,常見的有FIFO、優(yōu)先級、時間片輪詢、短任務優(yōu)先;
  2. 系統一般采取混合算法,因為不同進程特點不一樣,單一的調度算法不能滿足所有的場景;比如短任務算法需要在線程之間的切換消耗 和 任務真正執(zhí)行的消耗,兩者之間平衡,所以,每種調度算法都有自己的缺點和有點,混合算法是最高效的;
  3. 低等級的任務在訪問資源后使用自旋鎖進行加鎖,然后,高等級任務訪問同一個資源,因為該資源被加鎖,所以高等級任務等待鎖的釋放之后才能繼續(xù)工作。此時高等級任務一般會釋放 cpu 進入休眠。此時,一個中等級的任務開始執(zhí)行且不需要訪問被加鎖的資源,此時因為中等級的優(yōu)先級更高,所以直接搶占了低等級任務的 CPU。此時,低等級的任務只能處于 ready 狀態(tài)等待 CPU 分配,而高等級的任務在等待自旋鎖的釋放,處于休眠狀態(tài)。此時就出現了優(yōu)先級反轉,即:高等級的任務被分配的 CPU 低于中等級。
  4. 以上是高等級任務在等待時可以休眠的情況,也就是等待不是很占用cpu,這種情況下只是出現優(yōu)先級反轉,但是如果高優(yōu)先級任務的等待是忙循環(huán),也就會出現cpu把事件都分配給高級別任務,但是高級別任務又是忙循環(huán),低級別任務無法獲取cpu時間,最終就是死循環(huán),系統可能會崩潰;
  5. 另外,有一些機制會檢查高等級的 CPU 分配時間,如果一定時間內高等級的任務無法得到 CPU 時間片,則會認為系統除了故障,可能會進行重啟。宇航局的火星車,就是因為有高優(yōu)先級的線程被壓制,從而在指定時間內無法獲得 CPU,導致 “看門狗”認為系統出了無法恢復的故障,直接重啟了系統。重啟后系統再次進入相同狀態(tài),導致不斷重啟,無法正常工作。

二、os_unfair_lock

  1. 休眠,不是忙等待,是互斥鎖;
  2. iOS10之后才能使用,用于替換自旋鎖;

setProperty 中如果添加了 automic 關鍵字,則會使用互斥鎖進行加鎖:

image.png

這里的 spinlock_t 原來是自旋鎖,但是其實現方式已經被替換成了互斥鎖,只不過名稱沒有改過來而已:

image.png

三、pthread_mutex

  1. 跨平臺;
  2. 互斥鎖,等待屬于休眠;
  3. 可以設置類型,有:默認(PTHREAD_MUTEX_NORMAL)、遞歸所(PTHREAD_MUTEX_RECUSIVE)、錯誤檢查鎖(PTHREAD_MUTEX_ERRORCHECK);
  4. normal類型的鎖在創(chuàng)建時(pthread_mutex_init(&mutex,0))傳空即可,另外兩種鎖需要使用pthread_mutex_attr_settype來設置;
  5. 需要使用destory進行銷毀,attr、condition、mutex都需要銷毀;
  6. 遞歸鎖在遞歸時使用不會造成死鎖問題;
  7. 遞歸鎖:允許同一個線程對通一把鎖重復加鎖,加鎖次數和解鎖次數對應時才能解鎖;
  8. 條件鎖:pthread_cond_wait 和 pthread_cond_signal 配合使用;pthread_cond_wait(cond,mutex)會標記cond并解鎖mutex,線程進入休眠,并且阻塞代碼。當調用pthread_cond_signal(cond)之后,接收到信號后再對mutex進行加鎖,然后繼續(xù)執(zhí)行代碼;
  9. 條件所中的cond并不是類似于if else,而只是一個標記;
  10. 條件所一般用于解決線程以來問題,當一個線程任務的執(zhí)行需要以來另一個線程任務的執(zhí)行時使用,條件起到的是標記和傳遞的作用;
  11. 喚醒一個線程的等待使用pthread_cond_signal,喚醒所有等待的線程則使用廣播方法:pthread_cond_broadcast
  12. 條件等待時,調用signal方法發(fā)送信號之后,wait方法其實不是只判斷一次的,而是循環(huán)判斷檢測,如果這個鎖沒加鎖成功,就繼續(xù)等待,如果加鎖成功就返回,繼續(xù)執(zhí)行后面的代碼;所以,signal和unlock方法的調用順序差別不大,只有在兩者調用期間出現很大的延時操作時,wait方法會等待很久才加鎖成功,繼續(xù)執(zhí)行后面代碼。總之,邏輯不會受影響,只是時間問題,pthread_mutex內部已經考慮到這種問題,完成了解決方案的實現;

sqlite3 中也會使用到互斥鎖。sqlite3 為了效率和安全的平衡提供幾種模式:單線程模式下不加鎖,默認只能在單線程情況下使用。串行模式下因為全量加鎖,所以在多線程下使用時依然安全。還有一個是多線程模式,部分地方進行了加鎖,部分地方禁止了鎖,屬于一種折中方案:

image.png

四、自旋鎖和互斥鎖

  1. step:按行執(zhí)行代碼;si:按行執(zhí)行匯編代碼;
  2. 自旋鎖:忙等,相當于while循環(huán),在匯編中的體現是:jne -> 0xxxxxx ,條件成立則跳轉到指定地址循環(huán)執(zhí)行;
  3. 互斥鎖:等待時休眠,不占用cpu,類似于RunLoop;本質是:syscall,調用系統級別的函數去休眠并等待被喚醒的消息;
  4. OSSpinLoc是自旋鎖,os_unfair_lock和pthread_mutex是互斥鎖;

五、NSLock、NSRecusiveLock、NSCondition、NSConditionLock

  1. 是對pthread_mutex的封裝,封裝成了OC對象;

六、串行隊列

  1. async和sync決定是否可以開啟線程,隊列表示任務的執(zhí)行方式。
  2. 任務是一代碼塊為最小顆粒,而不是以一行代碼為最小顆粒。代碼塊中的每一行代碼默認都是同步執(zhí)行;
  3. sync表示從隊列中取出任務到當前線程執(zhí)行,async表示從隊列中取出任務異步執(zhí)行。所以,如果sync+serial queue 結果就是:可以將需要同步的任務(搶占資源的任務)添加到同一個queue中然后同步執(zhí)行,結果就是線程同步成功;

七、dispatch_semaphore

  1. dispatch_semaphore在初始化時需要使用create傳入一個最大信號量;
  2. 最大信號量意味著最多又多少條線程可以同時執(zhí)行,如果是1,那么就類似于串行隊列,所以也可以實現線程同步

dispatch_semaphore_wait(semaphore,time)的作用:

  1. 當semaphore>0時,讓當前線程直接繼續(xù)執(zhí)行,且dispatch_semaphore的值-1;
  2. 當semaphore<=0時,讓當前線程阻塞在這句代碼中,且讓線程休眠等待;
  3. time表示如果需要等待,那么最長等多久需要返回,傳now立馬進行判斷,傳forever就一直等;

dispatch_semaphore_signal(semaphore)的作用:

  1. 讓semaphore+1;

使用流程:

  1. 比如創(chuàng)建semaphore設置的最大信號量是5,有100個線程會執(zhí)行到這句代碼;
  2. 當第一次進入時,semaphore=5>0,所以就會讓當前進入,繼續(xù)執(zhí)行并且dispatch_semaphore-1=4;
  3. 假設dispatch_semaphore_wait和dispatch_semaphore_signal之間的代碼時耗時操作;
  4. 以此類推,當第五條線程進入之后,semaphore=0,而因為是耗時操作,所以100條線程都會執(zhí)行到dispatch_semaphore_wait代碼;
  5. 從第六條線程開始,因為dispatch_semaphore=0,線程被阻塞,剩余的95條線程如果在耗時操作沒有完成之前,也就是沒有調用dispatch_semaphore_signal之前,如果執(zhí)行到dispatch_semaphore_wait,那么都會處于休眠等待的狀態(tài);
  6. 當最先進入的線程執(zhí)行完耗時操作,調用dispatch_semaphore_signal,dispatch_semaphore+1>0,那么第六條線程就會從休眠中喚醒,繼續(xù)執(zhí)行后面的代碼;
  7. 以此類推…所以當semaphore初始化時設置為1,那么只有一條線程能夠訪問共享資源,如此便實現了線程同步;

八、@synchronized

  1. 底層仍然是pthread_mutex,是使用的recusive創(chuàng)建的遞歸鎖;
  2. 根據@synchronized(obj){}傳入的對象,生成一個和對象對應的一把鎖,存入到map表中;
  3. 關鍵字不能自動提示,因為存在性能問題,不被推薦使用;

九、性能對比

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

友情鏈接更多精彩內容