多線程

并發(fā) && 并行

多線程的同時執(zhí)行并非"并行", 而是"并發(fā)", "并發(fā)"無論從宏觀還是微觀上都是同時執(zhí)行的, 而"并行"宏觀上是同時執(zhí)行, 微觀上仍然是一個cpu的在多條線程上的來回切換.

多線程解決了什么問題?

從第一個問題可以看出, cpu(單核)在多條線程之間輪詢執(zhí)行的效率必然要低于單線程執(zhí)行. 在單核cpu的機(jī)器上單線程的效率是最高的. 所以多線程的出現(xiàn)并非是為了解決cpu的效率問題 (注意: 并非說多線程不能提高cpu的效率),而是為了解決"阻塞"問題, 如: task1 在 thread1 執(zhí)行需要10秒, task2 在 thread2 需要1秒, 人們不愿意等到 task1 執(zhí)行完成之后才能看到 task2 的執(zhí)行結(jié)果, 也就是不愿意 task1 阻塞 task2 的執(zhí)行. 可以說多線程是為了解決"阻塞"問題而生的.(多核cpu的問題涉及到硬件, 還不是很清楚, 不誤導(dǎo)大家了)

線程的串行

線程是進(jìn)程的執(zhí)行單元/路徑
一個線程中執(zhí)行多個任務(wù), 是按順序一個個執(zhí)行的

多線程的原理

CPU在各個線程中快速切換, 其調(diào)度線程的時間夠快, 就產(chǎn)生了多線程的"并發(fā)"執(zhí)行的假象

多線程優(yōu)缺點

優(yōu)點:

  1. 可以使任何需要及時響應(yīng)的任務(wù)及時響應(yīng), 如用戶UI可以在進(jìn)行其它工作的同時一直處于活動狀態(tài).
  2. 可以設(shè)置線程優(yōu)先級.
  3. 可以適當(dāng)提高資源利用率, 如: 下載速度最大總共1m/s的網(wǎng)絡(luò)環(huán)境下, 單線程下載 task1 && task2, 如果因為某些原因?qū)е孪螺dtask1的速度只有100k/s, 那么下載完這2個任務(wù)的時間必然很長; 如果開啟2條線程下載, 下載速度就可能達(dá)到1m/s, 如此大大提高了帶寬的利用率.

缺點:

  1. 如果線程多每條線程被調(diào)度執(zhí)行的頻次會降低(線程的執(zhí)行效率低).
  2. 線程占用內(nèi)存, 主線程默認(rèn)占1M, 子線程占用512k.
  3. 線程間通信和線程間數(shù)據(jù)共享, 資源搶奪造成程序的復(fù)雜性.

線程的狀態(tài)

  1. 可調(diào)度線程池概念
    系統(tǒng)底層用于管理線程的一個"池子", 裝著所有可供系統(tǒng)調(diào)度的線程.
  2. 線程的狀態(tài)
    1. new
      為線程分配內(nèi)存空間
    2. runnable
      線程進(jìn)入可調(diào)度線程池
    3. running
      線程有任務(wù)正在執(zhí)行
    4. blocked
      線程阻塞, 被移除可調(diào)度線程池
    5. dead
      線程死亡, 系統(tǒng)回收內(nèi)存

線程安全問題

  1. 資源搶占
    舉例: 如果一份文件需要張三和李四簽字, 可認(rèn)為2人對應(yīng)兩條線程, 若二人同時執(zhí)行簽字, 可能最后簽字結(jié)果是:張四李三, 李張三四等.
    若要解決此問題, 必須保證文件在同一段時間被一個人占用, 另一個人要么先"睡會", 要么"干點別的", "睡會"和"干點別的"對應(yīng)兩種線程鎖.

    1. 同步鎖: @synchronized
      用上面的例子, 張三在簽字的過程中, 把文件''鎖住'', 李四準(zhǔn)備來簽, 看到文件被鎖, 會"睡等"
    2. 自旋鎖 OSSpinLock
      用上面的例子, 張三在簽字的過程中, 把文件''鎖住'', 李四準(zhǔn)備來簽, 看到文件被鎖, 會"轉(zhuǎn)圈等".

兩種鎖的效率:
?對于同步鎖,如果資源已經(jīng)被占用,下一個調(diào)用者只能先進(jìn)入睡眠狀態(tài)等待。但是自旋鎖不會引起調(diào)用者睡眠,如果自旋鎖已經(jīng)被別的執(zhí)行單元保持,下一個調(diào)用者就一直循環(huán)在那里看是否該自旋鎖的保持者已經(jīng)釋放了鎖,"自旋"一詞就是因此而得名.
看上去 "自旋"會消耗大量資源, 效率更低. 實際情況是"睡"需要改變線程的狀態(tài), 會把線程從可調(diào)度線程池中取出, 從 runnable 狀態(tài)到blocked 狀態(tài). 而"自旋"在做一個空循環(huán), 不分配任何內(nèi)存空間, 相比與改變線程的狀態(tài)系統(tǒng)消耗的資源會少一些.

  1. 原子屬性
    atomic :消耗較多資源, 相對線程安全
    nonatomic:非線程安全

線程間通信

在一個進(jìn)程中, 線程往往不是孤立存在的, 多線程經(jīng)常需要相互通信:

  1. 一個線程傳遞數(shù)據(jù)給另一個線程
  2. 在一個線程中執(zhí)行完特定的任務(wù)后, 轉(zhuǎn)到另一個線程繼續(xù)執(zhí)行

iOS中多線程的實現(xiàn)方案

技術(shù) 簡介 語言 生命周期
pthread 跨平臺Unix Linux Windows C 需要管理
NSThread 面向?qū)ο?可直接操作線程對象 OC 需要管理
GCD 中樞調(diào)度系統(tǒng)(在隊列中調(diào)度任務(wù)到相應(yīng)線程) C 系統(tǒng)管理
NSOperation 對GCD的封裝, 面向?qū)ο?/td> OC 系統(tǒng)管理
  1. pthread
    基本過時, 很少能看見iOS項目中有使用
  • NSThread
    iOS中 NSThread 多用于的判斷線程編號, 是否處于主線程等

  • GCD

    1. 自動管理線程的生命周期 (創(chuàng)建線程, 調(diào)度任務(wù)), C,JAVA中需要關(guān)注
    2. 核心: 任務(wù)添加隊列, 任務(wù)的取出遵循隊列FIFO原則
      在 GCD 中,一個同步函數(shù)只在完成了它預(yù)定的任務(wù)后才返回。
      一個異步函數(shù),剛好相反,會立即返回,預(yù)定的任務(wù)會完成但不會等它完成.因此,一個異步函數(shù) . 不會阻塞當(dāng)前線程去執(zhí)行下一個函數(shù).
  • NSOperation

    1. 對GCD的封裝, 是GCD的進(jìn)一步抽象, NSOperation封裝了需要執(zhí)行的操作和執(zhí)行操作所需的數(shù)據(jù),讓程序員面向?qū)ο箝_發(fā).
    2. NSOperation本身是個抽象類,必須用其子類(系統(tǒng)提供子類, 也可以自定義子類)
    3. NSOperation 封裝了一些方法, 方便設(shè)置依賴, 方便取消操作, 方便判斷當(dāng)前操作的狀態(tài)等.
    4. 建議較為底層的, 公用的多線程模塊使用NSOperation, 其效率雖比GCD略低, 不過其面向?qū)ο笠约澳軐崿F(xiàn)繼承的優(yōu)點就足以讓程序員們?nèi)ナ褂?

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

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

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