电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

iOS 如何高效的使用多線程

瀏覽:6日期:2022-09-17 08:38:33

一、多線程簡述

線程是程序執(zhí)行流的最小單元,一個線程包括:獨有ID,程序計數(shù)器 (Program Counter),寄存器集合,堆棧。同一進程可以有多個線程,它們共享進程的全局變量和堆數(shù)據(jù)。

這里的 PC (Program Counter) 指向的是當(dāng)前的指令地址,通過 PC 的更新來運行我們的程序,一個線程同一時刻只能執(zhí)行一條指令。當(dāng)然我們知道線程和進程都是虛擬的概念,實際上 PC 是 CPU 核心中的寄存器,它是實際存在的,所以也可以說一個 CPU 核心同一時刻只能執(zhí)行一個線程。

不管是多處理器設(shè)備還是多核設(shè)備,開發(fā)者往往只需要關(guān)心 CPU 的核心數(shù)量,而不需關(guān)心它們的物理構(gòu)成。CPU 核心數(shù)量是有限的,也就是說一個設(shè)備并發(fā)執(zhí)行的線程數(shù)量是有限的,當(dāng)線程數(shù)量超過 CPU 核心數(shù)量時,一個 CPU 核心往往就要處理多個線程,這個行為叫做線程調(diào)度。

線程調(diào)度簡單來說就是:一個 CPU 核心輪流讓各個線程分別執(zhí)行一段時間。當(dāng)然這中間還包含著復(fù)雜的邏輯,后文再來分析。

二、多線程的優(yōu)化思路

在移動端開發(fā)中,因為系統(tǒng)的復(fù)雜性,開發(fā)者往往不能期望所有線程都能真正的并發(fā)執(zhí)行,而且開發(fā)者也不清楚 XNU 何時切換內(nèi)核態(tài)線程、何時進行線程調(diào)度,所以開發(fā)者要經(jīng)常考慮到線程調(diào)度的情況。

1、減少線程切換

當(dāng)線程數(shù)量超過 CPU 核心數(shù)量,CPU 核心通過線程調(diào)度切換用戶態(tài)線程,意味著有上下文的轉(zhuǎn)換(寄存器數(shù)據(jù)、棧等),過多的上下文切換會帶來資源開銷。雖然內(nèi)核態(tài)線程的切換理論上不會是性能負擔(dān),開發(fā)中還是應(yīng)該盡量減少線程的切換。

2、線程優(yōu)先級權(quán)衡

通常來說,線程調(diào)度除了輪轉(zhuǎn)法以外,還有優(yōu)先級調(diào)度的方案,在線程調(diào)度時,高優(yōu)先級的線程會更早的執(zhí)行。有兩個概念需要明確:

IO 密集型線程:頻繁等待的線程,等待的時候會讓出時間片。 CPU 密集型線程:很少等待的線程,意味著長時間占用著 CPU。

特殊場景下,當(dāng)多個 CPU 密集型線程霸占了所有 CPU 資源,而它們的優(yōu)先級都比較高,而此時優(yōu)先級較低的 IO 密集型線程將持續(xù)等待,產(chǎn)生線程餓死的現(xiàn)象。當(dāng)然,為了避免線程餓死,系統(tǒng)會逐步提高被“冷落”線程的優(yōu)先級,IO 密集型線程通常情況下比 CPU 密集型線程更容易獲取到優(yōu)先級提升。

雖然系統(tǒng)會自動做這些事情,但是這總歸會造成時間等待,可能會影響用戶體驗。所以筆者認(rèn)為開發(fā)者需要從兩個方面權(quán)衡優(yōu)先級問題:

讓 IO 密集型線程優(yōu)先級高于 CPU 密集型線程。 讓緊急的任務(wù)擁有更高的優(yōu)先級。

比如一個場景:大量的圖片異步解壓的任務(wù),解壓的圖片不需要立即反饋給用戶,同時又有大量的異步查詢磁盤緩存的任務(wù),而查詢磁盤緩存任務(wù)完成過后需要反饋給用戶。

圖片解壓屬于 CPU 密集型線程,查詢磁盤緩存屬于 IO 密集型線程,而后者需要反饋給用戶更加緊急,所以應(yīng)該讓圖片解壓線程的優(yōu)先級低一點,查詢磁盤緩存的線程優(yōu)先級高一點。

值得注意的是,這里是說大量的異步任務(wù),意味著 CPU 很有可能滿負荷運算,若 CPU 資源綽綽有余的情況下就沒那個必要去處理優(yōu)先級問題。

3、主線程任務(wù)的優(yōu)化

有些業(yè)務(wù)只能寫在主線程,比如 UI 類組件的初始化及其布局。其實這方面的優(yōu)化就比較多了,業(yè)界所說的性能優(yōu)化大部分都是為了減輕主線程的壓力,似乎有些偏離了多線程優(yōu)化的范疇了,下面就基于主線程任務(wù)的管理大致羅列幾點吧:

內(nèi)存復(fù)用

通過內(nèi)存復(fù)用來減少開辟內(nèi)存的時間消耗,這在系統(tǒng) UI 類組件中應(yīng)用廣泛,比如 UITableViewCell 的復(fù)用。同時,減少開辟內(nèi)存意味著減少了內(nèi)存釋放,同樣能節(jié)約 CPU 資源。

懶加載任務(wù)

既然 UI 組件必須在主線程初始化,那么就需要用時再初始化吧,swift 的寫時復(fù)制也是類似的思路。

任務(wù)拆分排隊執(zhí)行

通過監(jiān)聽 Runloop 即將結(jié)束等通知,將大量的任務(wù)拆分開來,在每次 Runloop 循環(huán)周期執(zhí)行少量任務(wù)。其實在實踐這種優(yōu)化思路之前,應(yīng)該想想能不能將任務(wù)放到異步線程,而不是用這種比較極端的優(yōu)化手段。

主線程空閑時執(zhí)行任務(wù)

//這里是主線程上下文`dispatch_async(dispatch_get_main_queue(), ^{//等到主線程空閑執(zhí)行該任務(wù)});

三、關(guān)于“鎖”

多線程會帶來線程安全問題,當(dāng)原子操作不能滿足業(yè)務(wù)時,往往需要使用各種“鎖”來保證內(nèi)存的讀寫安全。

常用的鎖有互斥鎖、讀寫鎖、空轉(zhuǎn)鎖,通常情況下,iOS 開發(fā)中互斥鎖pthread_mutex_t、dispatch_semaphore_t,讀寫鎖pthread_rwlock_t就能滿足大部分需求,并且性能不錯。

在讀取鎖失敗時,線程有可能有兩種狀態(tài):

空轉(zhuǎn)狀態(tài):線程執(zhí)行空任務(wù)循環(huán)等待,當(dāng)鎖可用時立即獲取鎖。 掛起狀態(tài):線程掛起,當(dāng)鎖可用時需要其他線程喚醒。

喚醒線程比較耗時,線程空轉(zhuǎn)需要消耗 CPU 資源并且時間越長消耗越多,由此可知空轉(zhuǎn)適合少量任務(wù)、掛起適合大量任務(wù)。

實際上互斥鎖和讀寫鎖都有空轉(zhuǎn)鎖的特性,它們在獲取鎖失敗時會先空轉(zhuǎn)一段時間,然后才會掛起,而空轉(zhuǎn)鎖也不會永遠的空轉(zhuǎn),在特定的空轉(zhuǎn)時間過后仍然會掛起,所以通常情況下不用刻意去使用空轉(zhuǎn)鎖,Casa Taloyum 在博客中有詳細的解釋。

1、OSSpinLock 優(yōu)先級反轉(zhuǎn)問題

優(yōu)先級反轉(zhuǎn)概念:比如兩個線程 A 和 B,優(yōu)先級 A < B。當(dāng) A 獲取鎖訪問共享資源時,B 嘗試獲取鎖,那么 B 就會進入忙等狀態(tài),忙等時間越長對 CPU 資源的占用越大;而由于 A 的優(yōu)先級低于 B,A 無法與高優(yōu)先級的線程爭奪 CPU 資源,從而導(dǎo)致任務(wù)遲遲完成不了。解決優(yōu)先級反轉(zhuǎn)的方法有“優(yōu)先級天花板”和“優(yōu)先級繼承”,它們的核心操作都是提升當(dāng)前正在訪問共享資源的線程的優(yōu)先級。

2、避免死鎖

很常見的場景是,同一線程重復(fù)獲取鎖導(dǎo)致的死鎖,這種情況可以使用遞歸鎖來處理,pthread_mutex_t使用pthread_mutex_init_recursive()方法初始化就能擁有遞歸鎖的特性。

使用pthread_mutex_trylock()等嘗試獲取鎖的方法能有效的避免死鎖的情況

3、最小化加鎖任務(wù)

開發(fā)者應(yīng)該充分的理解業(yè)務(wù),將鎖包含的代碼區(qū)域盡量縮小,不會出現(xiàn)線程安全問題 的代碼就不要用鎖來保護了,這樣才能提高并發(fā)時鎖的性能。

4、時刻注意不可重入方法的安全

當(dāng)一個方法是可重入的時候,可以放心大膽的使用,若一個方法不可重入,開發(fā)者應(yīng)該多留意,思考這個方法會不會有多個線程訪問的情況,若有就老老實實的加上線程鎖。

5、編譯器的過度優(yōu)化

編譯器可能會為了提高效率將變量寫入寄存器而暫時不寫回,方便下次使用,我們知道一句代碼轉(zhuǎn)換為指令不止一條,所以在變量寫入寄存器沒來得及寫回的過程中,可能這個變量被其它線程讀寫了。編譯器同樣會為了提高效率對它認(rèn)為順序無關(guān)的指令調(diào)換順序。

以上都可能會導(dǎo)致合理使用鎖的地方仍然線程不安全,而volatile關(guān)鍵字就可以解決這類問題,它能阻止編譯器為了效率將變量緩存到寄存器而不及時寫回,也能阻止編譯器調(diào)整操作volatile修飾變量的指令順序。

原子自增函數(shù)就有類似的應(yīng)用: int32_t OSAtomicIncrement32( volatile int32_t *__theValue ) 。

6、CPU 亂序執(zhí)行

CPU 也可能為了提高效率而去交換指令的順序,導(dǎo)致加鎖的代碼也不安全,解決這類問題可以使用內(nèi)存屏障,CPU 越過內(nèi)存屏障后會刷新寄存器對變量的分配。

以上就是iOS 如何高效使用的多線程的詳細內(nèi)容,更多關(guān)于ios 多線程的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: IOS
相關(guān)文章:
主站蜘蛛池模板: 破碎机锤头_耐磨锤头_合金锤头-鼎成机械一站式耐磨铸件定制服务 微型驱动系统解决方案-深圳市兆威机电股份有限公司 | 小威小说网 - 新小威小说网 - 小威小说网小说搜索引擎 | 大行程影像测量仪-探针型影像测量仪-增强型影像测量仪|首丰百科 大通天成企业资质代办_承装修试电力设施许可证_增值电信业务经营许可证_无人机运营合格证_广播电视节目制作许可证 | 南汇8424西瓜_南汇玉菇甜瓜-南汇水蜜桃价格 | 武汉画册印刷厂家-企业画册印刷-画册设计印刷制作-宣传画册印刷公司 - 武汉泽雅印刷厂 | 行吊_电动单梁起重机_双梁起重机_合肥起重机_厂家_合肥市神雕起重机械有限公司 | 六维力传感器_六分量力传感器_模腔压力传感器-南京数智微传感科技有限公司 | 合肥网带炉_安徽箱式炉_钟罩炉-合肥品炙装备科技有限公司 | 运动木地板厂家,篮球场木地板品牌,体育场馆木地板安装 - 欧氏运动地板 | 棉柔巾代加工_洗脸巾oem_一次性毛巾_浴巾生产厂家-杭州禾壹卫品科技有限公司 | 泥浆在线密度计厂家-防爆数字压力表-膜盒-远传压力表厂家-江苏大亚自控设备有限公司 | 断桥铝破碎机_铝合金破碎机_废铁金属破碎机-河南鑫世昌机械制造有限公司 | 耙式干燥机_真空耙式干燥机厂家-无锡鹏茂化工装备有限公司 | 杭州货架订做_组合货架公司_货位式货架_贯通式_重型仓储_工厂货架_货架销售厂家_杭州永诚货架有限公司 | 鄂泉泵业官网|(杭州、上海、全国畅销)大流量防汛排涝泵-LW立式排污泵 | 箱式破碎机_移动方箱式破碎机/价格/厂家_【华盛铭重工】 | 聚氨酯催化剂K15,延迟催化剂SA-1,叔胺延迟催化剂,DBU,二甲基哌嗪,催化剂TMR-2,-聚氨酯催化剂生产厂家 | 铝合金脚手架厂家-专注高空作业平台-深圳腾达安全科技 | 工业风机_环保空调_冷风机_工厂车间厂房通风降温设备旺成服务平台 | 球盟会·(中国)官方网站| 数控车床-立式加工中心-多功能机床-小型车床-山东临沂金星机床有限公司 | 「安徽双凯」自动售货机-无人售货机-成人用品-自动饮料食品零食售货机 | 减速机三参数组合探头|TSM803|壁挂式氧化锆分析仪探头-安徽鹏宸电气有限公司 | 土壤肥料养分速测仪_测土配方施肥仪_土壤养分检测仪-杭州鸣辉科技有限公司 | 全自动翻转振荡器-浸出式水平振荡器厂家-土壤干燥箱价格-常州普天仪器 | 流水线电子称-钰恒-上下限报警电子秤-上海宿衡实业有限公司 | 集装箱展厅-住人集装箱住宿|建筑|房屋|集装箱售楼处-山东锐嘉科技工程有限公司 | 比士亚-专业恒温恒湿酒窖,酒柜,雪茄柜的设计定制 | 红立方品牌应急包/急救包加盟,小成本好项目代理_应急/消防/户外用品加盟_应急好项目加盟_新奇特项目招商 - 中红方宁(北京) 供应链有限公司 | 长春网站建设,五合一网站设计制作,免费优化推广-长春网站建设 | 防水套管_柔性防水套管_刚性防水套管-巩义市润达管道设备制造有限公司 | 查分易-成绩发送平台官网| 结晶点测定仪-润滑脂滴点测定仪-大连煜烁 | 皮带机-带式输送机价格-固定式胶带机生产厂家-河南坤威机械 | 气胀轴|气涨轴|安全夹头|安全卡盘|伺服纠偏系统厂家-天机传动 | 重庆LED显示屏_显示屏安装公司_重庆LED显示屏批发-彩光科技公司 重庆钣金加工厂家首页-专业定做监控电视墙_操作台 | 北京网站建设-企业网站建设-建站公司-做网站-北京良言多米网络公司 | 雄松华章(广州华章MBA)官网-专注MBA/MPA/MPAcc/MEM辅导培训 | 密封无忧网 _ 专业的密封产品行业信息网 | 达利园物流科技集团-| 云南丰泰挖掘机修理厂-挖掘机维修,翻新,再制造的大型企业-云南丰泰工程机械维修有限公司 |