最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

進(jìn)程與線程的關(guān)系

2022-10-31 17:18 作者:游戲開發(fā)RAIN  | 我要投稿

很多人對(duì)進(jìn)程,線程沒有什么概念,或者面試的時(shí)候說不出里面的核心內(nèi)涵,今天我打算花一點(diǎn)篇 幅把進(jìn)程和線程講清楚。

? ??1: CPU與內(nèi)存

CPU 大家都知道是計(jì)算機(jī)的中央運(yùn)算單元,用來計(jì)算的。CPU從內(nèi)存里面讀取一條一條的代碼指令,然后根據(jù)指令來執(zhí)行運(yùn)算(加,減,乘,除,復(fù)制數(shù)據(jù)等)。 CPU在運(yùn)算的過程中一些數(shù)據(jù)存放在CPU的寄存器和內(nèi)存里面, CPU里面有各種寄存器,各司其職。指令指針寄存器存放的是當(dāng)前執(zhí)行到那條代碼指令了。代碼指令是寫完程序后被編譯器編譯成二進(jìn)制指令代碼


2: 內(nèi)核與虛擬內(nèi)存。

電腦或手機(jī)開機(jī)以后,上電跑啟動(dòng)代碼,運(yùn)行OS內(nèi)核,內(nèi)核里也有線程,這個(gè)我們把它叫做內(nèi)核態(tài)。內(nèi)核啟動(dòng)以后, ?內(nèi)核將物理內(nèi)存管理起來。內(nèi)核提供虛擬內(nèi)存管理機(jī)制給每個(gè)進(jìn)程(應(yīng)用程序App)內(nèi)存服務(wù)。它的思路是什么呢?每個(gè)進(jìn)程(應(yīng)用App) 都有自己的虛擬內(nèi)存空間,注意這里的空間只是一個(gè)數(shù)字空間,沒有劃分實(shí)際的物理內(nèi)存。這樣做的好處是多個(gè)進(jìn)程(應(yīng)用App)內(nèi)存都是獨(dú)立的相互不影響,物理內(nèi)存只有一個(gè),多個(gè)進(jìn)程(應(yīng)用App)不會(huì)因?yàn)橹苯邮褂梦锢韮?nèi)存而沖突。那么OS是如何管理物理內(nèi)存的呢?進(jìn)程(應(yīng)用App)需要內(nèi)存的時(shí)候,OS分配一塊虛擬內(nèi)存(起點(diǎn)---終點(diǎn)),然后OS在從自己管理的物理內(nèi)存里面分配出來物理內(nèi)存頁(yè),然后通過一個(gè)MMU的單元,將分配的虛擬內(nèi)存與物理內(nèi)存頁(yè)映射起來,這樣,讀寫虛擬內(nèi)存地址最終通過映射來使用物理內(nèi)存地址,這樣每個(gè)進(jìn)程之間的內(nèi)存是獨(dú)立的,安全的。每個(gè)進(jìn)程會(huì)把虛擬內(nèi)存空間分成4個(gè)段(代碼段, 數(shù)據(jù)端,堆,棧)

代碼段:用來存放進(jìn)程(應(yīng)用App)的代碼指令。

數(shù)據(jù)端: ?用來存放全局變量的內(nèi)存。

: 調(diào)用osmalloc/free 來動(dòng)態(tài)分配的內(nèi)存。

: 用來存放局部變量,函數(shù)參數(shù),函數(shù)調(diào)用與跳轉(zhuǎn)。

每個(gè)進(jìn)程(應(yīng)用App)相當(dāng)于一個(gè)容器,所有應(yīng)用App里面需要的資源和機(jī)制都在進(jìn)程里面。線程是OS獨(dú)立調(diào)度執(zhí)行的單元,OS調(diào)度執(zhí)行的單位就是線程,線程需要以進(jìn)程作為容器和使用進(jìn)程相關(guān)的環(huán)境。

應(yīng)用態(tài)沒有進(jìn)程就不會(huì)有線程。

3: 進(jìn)程與線程

上面說過進(jìn)程是容器,應(yīng)用態(tài)的線程必須要基于進(jìn)程來創(chuàng)建出來。那么進(jìn)程與線程他們之間到底是一個(gè)什么樣的關(guān)系,接下來我們來分析一下。例如"在桌面上雙擊打開一個(gè)App", 桌面App程序會(huì)調(diào)用OS的系統(tǒng)調(diào)用接口fork,讓OS 創(chuàng)建一個(gè)進(jìn)程出來, OS為你準(zhǔn)備好進(jìn)程的結(jié)構(gòu)體對(duì)象,將這個(gè)App的文件(xxx.exe, 存放編譯好的代碼指令)加載到進(jìn)程的代碼段,同時(shí)OS會(huì)為你創(chuàng)建一個(gè)線程(main thread), 在代碼里面,你還可以調(diào)用OS的接口,來創(chuàng)建多個(gè)線程。這樣OS就可以調(diào)度這些線程執(zhí)行了。?虛擬內(nèi)存空間是進(jìn)程的概念,那么線程如何使用的呢?各線程使用共享進(jìn)程的代碼段,數(shù)據(jù)段,堆,每個(gè)線程在進(jìn)程的??臻g創(chuàng)建一個(gè)屬于自己的??臻g。所以這樣就得到一些結(jié)論如下:

?????每個(gè)線程共享進(jìn)程的代碼段內(nèi)存空間,所以我們編寫多線程代碼的時(shí)候,可以在任何線程調(diào)用任何函數(shù)。

????每個(gè)線程共享進(jìn)程的數(shù)據(jù)段內(nèi)存空間,所以我們編寫多線程代碼的時(shí)候,可以在任何線程訪問全局變量。

???每個(gè)線程共享進(jìn)程的堆,所以我們編寫多線程代碼的時(shí)候,可以在一個(gè)線程訪問另外一個(gè)線程new/malloc出來的內(nèi)存對(duì)象。

???每個(gè)線程都有自己的棧的空間,所以可以獨(dú)立調(diào)用執(zhí)行函數(shù)(參數(shù),局部變量,函數(shù)跳轉(zhuǎn))相互之間不受影響。

4: OS如何調(diào)度線程的。

????CPU一般會(huì)有多個(gè)核心,每個(gè)核心都調(diào)度一個(gè)線程執(zhí)行。CPU有幾個(gè)核心,最多同時(shí)可調(diào)度幾個(gè)線程(多核能讓電腦更快就是這個(gè)原理)。OS的功能就是要在合適的時(shí)候分配CPU核心來調(diào)度合適的線程。為了能實(shí)現(xiàn)多任務(wù)并發(fā),OS不允許一個(gè)OS核心長(zhǎng)期固定調(diào)度一個(gè)線程。

????OS是如何調(diào)度CPU核心來執(zhí)行各個(gè)線程呢? OS會(huì)根據(jù)線程的優(yōu)先級(jí)分配每次調(diào)度最多執(zhí)行的時(shí)間片,這個(gè)時(shí)間一到,不管怎么樣,都要重新調(diào)度一次線程(也許還是調(diào)度到這個(gè)線程,這個(gè)不重要)。除了時(shí)間片以外,線程會(huì)等待某些條件(磁盤讀取文件,網(wǎng)卡發(fā)送完數(shù)據(jù), 線程休眠, 等待用戶操作)這樣也會(huì)把這個(gè)線程掛起,OS會(huì)重新找一個(gè)新的線程繼續(xù)執(zhí)行,只到掛起的這個(gè)線程的條件滿足了,重新把這個(gè)線程放到可調(diào)度隊(duì)列里面,這個(gè)線程又有機(jī)會(huì)被OS調(diào)度CPU核心來執(zhí)行。當(dāng)我們打開電腦的任務(wù)管理器,你會(huì)發(fā)現(xiàn)很多線程的CPU占有率為0%, 說明這些線程都由于某些條件而掛起了。沒有被OS調(diào)度。

???每個(gè)線程“隨時(shí)隨地”都可能被OS 中斷執(zhí)行,并調(diào)度到其它的線程執(zhí)行。OS是如何保證一個(gè)線程在調(diào)度出去后,再重新調(diào)度回來能繼續(xù)之前的數(shù)據(jù)狀態(tài)來執(zhí)行呢?OS是這么做到的。每個(gè)線程都會(huì)有一個(gè)運(yùn)行時(shí)的環(huán)境(運(yùn)行時(shí)CPU的每個(gè)寄存器的值, 棧獨(dú)立, 棧的內(nèi)存數(shù)據(jù)不會(huì)變。數(shù)據(jù)段,堆共用,可能調(diào)度回來會(huì)變)。當(dāng)OS要把某個(gè)CPU核心調(diào)度出去給其它線程的時(shí)候,首先會(huì)把當(dāng)前線程的運(yùn)行環(huán)境(寄存器的值等)保存到內(nèi)存,然后調(diào)度到其它線程,等再次調(diào)度回來的時(shí)候,再把原來保存到內(nèi)存的寄存器的值,再設(shè)置會(huì)CPU核心的寄存器里面,這樣就回到了調(diào)度出去之前的進(jìn)度。

???調(diào)度回來以后,有些會(huì)改變,因?yàn)槎嗑€程之間共用了代碼段(代碼段只讀,不會(huì)改),數(shù)據(jù)段(全局變量調(diào)度回來后,可能被其它線程篡改,不是調(diào)度之前的那個(gè)值了), 堆(調(diào)度回來后,動(dòng)態(tài)內(nèi)存分配的對(duì)象內(nèi)存數(shù)據(jù)可能被其它線程出篡改),調(diào)度回來后,棧上的數(shù)據(jù)是不變的,因?yàn)槊總€(gè)線程都有自己的棧空間。線程調(diào)度前后哪些會(huì)變,哪些不變你要清楚。這樣你寫多線程代碼的時(shí)候才能清晰。

?線程調(diào)度的開銷就是:保存上下文執(zhí)行環(huán)境,內(nèi)核態(tài)運(yùn)行算法決定接下來調(diào)度那個(gè)線程,切換這個(gè)線程的上下文環(huán)境。

? ?5: 線程鎖的核心原理是什么?

多線程切換的時(shí)候,棧,代碼段的數(shù)據(jù)不會(huì)變,數(shù)據(jù)段與堆的數(shù)據(jù)切換前后可能會(huì)發(fā)生改變,這個(gè)就造成了"競(jìng)爭(zhēng)", 如果某些關(guān)鍵數(shù)據(jù),在執(zhí)行代碼的時(shí)候,不允許這種競(jìng)爭(zhēng)性的改變,怎么辦呢?這個(gè)時(shí)候多線程就給了一個(gè)機(jī)制,這個(gè)機(jī)制就是鎖,那么鎖的原理是什么?接下來我來和你詳細(xì)的講解。

例如: 我編寫一個(gè)函數(shù),

funcA() {

????lock(鎖) ??// 要保護(hù)的數(shù)據(jù)的邏輯部分。

????…

????unlock(鎖)

}

?當(dāng)線程A調(diào)用FuncA(),線程B也調(diào)用FUNCA(),OS如何設(shè)計(jì)鎖能保證他們競(jìng)爭(zhēng)的唯一性的呢?我們把具體過程來分析一下。

假設(shè)線程A調(diào)用funcA(); ?它獲取了鎖,執(zhí)行到中間某個(gè)代碼的時(shí)候,時(shí)間片用完了,被OS調(diào)度出去,OS調(diào)度線程B來執(zhí)行funcA(), 這個(gè)時(shí)候,當(dāng)線程B跑到lock()的時(shí)候,發(fā)現(xiàn)這個(gè)鎖已經(jīng)被線程A拿了,這個(gè)時(shí)候,線程B會(huì)主動(dòng)把自己掛起到鎖這個(gè)“事件”上(等著鎖釋放)。OS從新調(diào)度線程執(zhí)行,當(dāng)重新調(diào)度到線程A的時(shí)候,線程A執(zhí)行,執(zhí)行完成以后,釋放掉這個(gè)鎖,那么線程B又從等待這個(gè)鎖的隊(duì)列,到線程調(diào)度的就緒隊(duì)列,又可被OS調(diào)度到,等線程A調(diào)度出去后,線程Block這個(gè)鎖,就占用了這個(gè)鎖,然后繼續(xù)執(zhí)行。這樣就保證了lock/unlock之間的代碼永遠(yuǎn)只有一個(gè)線程跑進(jìn)去了。這樣保護(hù)了這段代碼里面相關(guān)的數(shù)據(jù)和邏輯。

?進(jìn)程與線程各位鐵鐵一定要掌握好,這樣你寫程序才能做到心中用代碼, 今天的分享就到這里了,謝謝再見。

?



進(jìn)程與線程的關(guān)系的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
余江县| 枣强县| 海盐县| 镇赉县| 凤台县| 沅江市| 中西区| 竹山县| 青州市| 清镇市| 隆回县| 浦江县| 延津县| 安庆市| 玛纳斯县| 新闻| 合水县| 乳源| 阿拉尔市| 怀柔区| 三原县| 咸宁市| 济南市| 唐河县| 宜黄县| 阿坝县| 鹿邑县| 龙江县| 政和县| 濮阳市| 同江市| 双城市| 龙海市| 乳山市| 宜兴市| 龙游县| 谷城县| 页游| 古蔺县| 任丘市| 来宾市|