寫在前面:
找工作告一段落,期間經(jīng)歷了很多事情谴咸,也思考了許多問題轮听,最后也收獲了一些沉甸甸的東西 —— 成長和一些來自阿里、百度岭佳、京東(sp)血巍、華為等廠的Offer。好在一切又回到正軌珊随,接下來要好好總結(jié)一番才不枉這段經(jīng)歷述寡,遂將此過程中筆者的一些筆試/面試心得、干貨發(fā)表出來叶洞,與眾共享之鲫凶。
進(jìn)程和線程以及它們的區(qū)別
- 進(jìn)程是對運行時程序的封裝,是系統(tǒng)進(jìn)行資源調(diào)度和分配的的基本單位艺晴,實現(xiàn)了操作系統(tǒng)的并發(fā)昼钻;
- 線程是進(jìn)程的子任務(wù)掸屡,是CPU調(diào)度和分派的基本單位,用于保證程序的 實時性然评,實現(xiàn)進(jìn)程內(nèi)部的并發(fā)蝉衣;
- 一個程序至少有一個進(jìn)程羹令,一個進(jìn)程至少有一個線程,線程依賴于進(jìn)程而存在;
- 進(jìn)程在執(zhí)行過程中擁有獨立的內(nèi)存單元阿纤,而多個線程共享進(jìn)程的內(nèi)存。
進(jìn)程間的通信的幾種方式
- 管道(pipe)及命名管道(named pipe):管道可用于具有親緣關(guān)系的父子進(jìn)程間的通信藤为,有名管道除了具有管道所具有的功能外柱衔,它還允許無親緣關(guān)系進(jìn)程間的通信;
- 信號(signal):信號是一種比較復(fù)雜的通信方式缕探,用于通知接收進(jìn)程某個事件已經(jīng)發(fā)生魂莫;
- 消息隊列:消息隊列是消息的鏈接表,它克服了上兩種通信方式中信號量有限的缺點爹耗,具有寫權(quán)限得進(jìn)程可以按照一定得規(guī)則向消息隊列中添加新信息耙考;對消息隊列有讀權(quán)限得進(jìn)程則可以從消息隊列中讀取信息;
- 共享內(nèi)存:可以說這是最有用的進(jìn)程間通信方式潭兽。它使得多個進(jìn)程可以訪問同一塊內(nèi)存空間倦始,不同進(jìn)程可以及時看到對方進(jìn)程中對共享內(nèi)存中數(shù)據(jù)得更新。這種方式需要依靠某種同步操作山卦,如互斥鎖和信號量等鞋邑;
- 信號量:主要作為進(jìn)程之間及同一種進(jìn)程的不同線程之間得同步和互斥手段;
- 套接字:這是一種更為一般得進(jìn)程間通信機(jī)制账蓉,它可用于網(wǎng)絡(luò)中不同機(jī)器之間的進(jìn)程間通信枚碗,應(yīng)用非常廣泛。
線程同步的方式
- 互斥量 Synchronized/Lock:采用互斥對象機(jī)制铸本,只有擁有互斥對象的線程才有訪問公共資源的權(quán)限肮雨。因為互斥對象只有一個,所以可以保證公共資源不會被多個線程同時訪問
- 信號量 Semphare:它允許同一時刻多個線程訪問同一資源箱玷,但是需要控制同一時刻訪問此資源的最大線程數(shù)量
- 事件(信號)怨规,Wait/Notify:通過通知操作的方式來保持多線程同步,還可以方便的實現(xiàn)多線程優(yōu)先級的比較操作
什么是死鎖汪茧?死鎖產(chǎn)生的條件椅亚?
死鎖的概念
在兩個或者多個并發(fā)進(jìn)程中,如果每個進(jìn)程持有某種資源而又等待其它進(jìn)程釋放它或它們現(xiàn)在保持著的資源舱污,在未改變這種狀態(tài)之前都不能向前推進(jìn)呀舔,稱這一組進(jìn)程產(chǎn)生了死鎖。通俗的講,就是兩個或多個進(jìn)程無限期的阻塞媚赖、相互等待的一種狀態(tài)霜瘪。
死鎖產(chǎn)生的四個必要條件
- 互斥:至少有一個資源必須屬于非共享模式,即一次只能被一個進(jìn)程使用惧磺;若其他申請使用該資源颖对,那么申請進(jìn)程必須等到該資源被釋放為止;
- 占有并等待:一個進(jìn)程必須占有至少一個資源磨隘,并等待另一個資源缤底,而該資源為其他進(jìn)程所占有;
- 非搶占:進(jìn)程不能被搶占番捂,即資源只能被進(jìn)程在完成任務(wù)后自愿釋放
- 循環(huán)等待:若干進(jìn)程之間形成一種頭尾相接的環(huán)形等待資源關(guān)系
死鎖的處理基本策略和常用方法
解決死鎖的基本方法主要有 預(yù)防死鎖个唧、避免死鎖、檢測死鎖设预、解除死鎖 徙歼、鴕鳥策略 等。
死鎖預(yù)防
死鎖預(yù)防的基本思想是 只要確保死鎖發(fā)生的四個必要條件中至少有一個不成立鳖枕,就能預(yù)防死鎖的發(fā)生魄梯,具體方法包括:
- 打破互斥條件:允許進(jìn)程同時訪問某些資源。但是宾符,有些資源是不能被多個進(jìn)程所共享的酿秸,這是由資源本身屬性所決定的,因此魏烫,這種辦法通常并無實用價值。
- 打破占有并等待條件:可以實行資源預(yù)先分配策略(進(jìn)程在運行前一次性向系統(tǒng)申請它所需要的全部資源则奥,若所需全部資源得不到滿足狭园,則不分配任何資源,此進(jìn)程暫不運行唱矛;只有當(dāng)系統(tǒng)能滿足當(dāng)前進(jìn)程所需的全部資源時,才一次性將所申請資源全部分配給該線程)或者只允許進(jìn)程在沒有占用資源時才可以申請資源(一個進(jìn)程可申請一些資源并使用它們绎谦,但是在當(dāng)前進(jìn)程申請更多資源之前,它必須全部釋放當(dāng)前所占有的資源)窃肠。但是這種策略也存在一些缺點:在很多情況下,無法預(yù)知一個進(jìn)程執(zhí)行前所需的全部資源冤留,因為進(jìn)程是動態(tài)執(zhí)行的树灶,不可預(yù)知的糯而;同時,會降低資源利用率熄驼,導(dǎo)致降低了進(jìn)程的并發(fā)性像寒。
- 打破非搶占條件:允許進(jìn)程強(qiáng)行從占有者哪里奪取某些資源。也就是說瓜贾,但一個進(jìn)程占有了一部分資源诺祸,在其申請新的資源且得不到滿足時,它必須釋放所有占有的資源以便讓其它線程使用阐虚。這種預(yù)防死鎖的方式實現(xiàn)起來困難序臂,會降低系統(tǒng)性能。
- 打破循環(huán)等待條件:實行資源有序分配策略实束。對所有資源排序編號奥秆,所有進(jìn)程對資源的請求必須嚴(yán)格按資源序號遞增的順序提出,即只有占用了小號資源才能申請大號資源咸灿,這樣就不回產(chǎn)生環(huán)路构订,預(yù)防死鎖的發(fā)生。
死鎖避免的基本思想
死鎖避免的基本思想是動態(tài)地檢測資源分配狀態(tài)避矢,以確保循環(huán)等待條件不成立悼瘾,從而確保系統(tǒng)處于安全狀態(tài)。所謂安全狀態(tài)是指:如果系統(tǒng)能按某個順序為每個進(jìn)程分配資源(不超過其最大值)审胸,那么系統(tǒng)狀態(tài)是安全的亥宿,換句話說就是,如果存在一個安全序列砂沛,那么系統(tǒng)處于安全狀態(tài)烫扼。資源分配圖算法和銀行家算法是兩種經(jīng)典的死鎖避免的算法,其可以確保系統(tǒng)始終處于安全狀態(tài)碍庵。其中映企,資源分配圖算法應(yīng)用場景為每種資源類型只有一個實例(申請邊,分配邊静浴,需求邊堰氓,不形成環(huán)才允許分配),而銀行家算法應(yīng)用于每種資源類型可以有多個實例的場景苹享。
死鎖解除
死鎖解除的常用兩種方法為進(jìn)程終止和資源搶占双絮。所謂進(jìn)程終止是指簡單地終止一個或多個進(jìn)程以打破循環(huán)等待,包括兩種方式:終止所有死鎖進(jìn)程和一次只終止一個進(jìn)程直到取消死鎖循環(huán)為止;所謂資源搶占是指從一個或多個死鎖進(jìn)程那里搶占一個或多個資源掷邦,此時必須考慮三個問題:
- 選擇一個犧牲品
- 回滾:回滾到安全狀態(tài)
- 饑餓(在代價因素中加上回滾次數(shù)白胀,回滾的越多則越不可能繼續(xù)被作為犧牲品,避免一個進(jìn)程總是被回滾)
進(jìn)程有哪幾種狀態(tài)或杠?
- 就緒狀態(tài):進(jìn)程已獲得除處理機(jī)以外的所需資源宣蔚,等待分配處理機(jī)資源胚委;
- 運行狀態(tài):占用處理機(jī)資源運行,處于此狀態(tài)的進(jìn)程數(shù)小于等于CPU數(shù)艘希;
- 阻塞狀態(tài): 進(jìn)程等待某種條件覆享,在條件滿足之前無法執(zhí)行撒顿;
線程有幾種狀態(tài)?
在 Java虛擬機(jī) 中厌衙,線程從最初的創(chuàng)建到最終的消亡婶希,要經(jīng)歷若干個狀態(tài):創(chuàng)建(new)、就緒(runnable/start)狰晚、運行(running)缴啡、阻塞(blocked)业栅、等待(waiting)、時間等待(time waiting) 和 消亡(dead/terminated)携取。在給定的時間點上雷滋,一個線程只能處于一種狀態(tài)晤斩,各狀態(tài)的含義如下圖所示:
線程各狀態(tài)之間的轉(zhuǎn)換如下:
分頁和分段有什么區(qū)別(內(nèi)存管理)原探?
段式存儲管理是一種符合用戶視角的內(nèi)存分配管理方案。在段式存儲管理中徒蟆,將程序的地址空間劃分為若干段(segment)段审,如代碼段,數(shù)據(jù)段裸诽,堆棧段丈冬;這樣每個進(jìn)程有一個二維地址空間埂蕊,相互獨立疏唾,互不干擾槐脏。段式管理的優(yōu)點是:沒有內(nèi)碎片(因為段大小可變顿天,改變段大小來消除內(nèi)碎片)。但段換入換出時咽白,會產(chǎn)生外碎片(比如4k的段換5k的段晶框,會產(chǎn)生1k的外碎片)
頁式存儲管理方案是一種用戶視角內(nèi)存與物理內(nèi)存相分離的內(nèi)存分配管理方案授段。在頁式存儲管理中畴蒲,將程序的邏輯地址劃分為固定大小的頁(page)对室,而物理內(nèi)存劃分為同樣大小的幀掩宜,程序加載時牺汤,可以將任意一頁放入內(nèi)存中任意一個幀,這些幀不必連續(xù)补胚,從而實現(xiàn)了離散分離溶其。頁式存儲管理的優(yōu)點是:沒有外碎片(因為頁的大小固定)瓶逃,但會產(chǎn)生內(nèi)碎片(一個頁可能填充不滿)廓块。
兩者的不同點:
- 目的不同:分頁是由于系統(tǒng)管理的需要而不是用戶的需要带猴,它是信息的物理單位拴清;分段的目的是為了能更好地滿足用戶的需要,它是信息的邏輯單位嫡秕,它含有一組其意義相對完整的信息昆咽;
- 大小不同:頁的大小固定且由系統(tǒng)決定掷酗,而段的長度卻不固定窟哺,由其所完成的功能決定且轨;
- 地址空間不同: 段向用戶提供二維地址空間;頁向用戶提供的是一維地址空間泳挥;
- 信息共享:段是信息的邏輯單位屉符,便于存儲保護(hù)和信息的共享,頁的保護(hù)和共享受到限制唆香;
- 內(nèi)存碎片:頁式存儲管理的優(yōu)點是沒有外碎片(因為頁的大小固定)躬它,但會產(chǎn)生內(nèi)碎片(一個頁可能填充不滿)虑凛;而段式管理的優(yōu)點是沒有內(nèi)碎片(因為段大小可變软啼,改變段大小來消除內(nèi)碎片)祸挪。但段換入換出時,會產(chǎn)生外碎片(比如4k的段換5k的段雹仿,會產(chǎn)生1k的外碎片)整以。
操作系統(tǒng)中進(jìn)程調(diào)度策略有哪幾種公黑?
- FCFS(先來先服務(wù)凡蚜,隊列實現(xiàn),非搶占的):先請求CPU的進(jìn)程先分配到CPU
- SJF(最短作業(yè)優(yōu)先調(diào)度算法):平均等待時間最短恶迈,但難以知道下一個CPU區(qū)間長度
- 優(yōu)先級調(diào)度算法(可以是搶占的暇仲,也可以是非搶占的):優(yōu)先級越高越先分配到CPU,相同優(yōu)先級先到先服務(wù)辆床,存在的主要問題是:低優(yōu)先級進(jìn)程無窮等待CPU桅狠,會導(dǎo)致無窮阻塞或饑餓中跌;解決方案:老化
- 時間片輪轉(zhuǎn)調(diào)度算法(可搶占的):隊列中沒有進(jìn)程被分配超過一個時間片的CPU時間漩符,除非它是唯一可運行的進(jìn)程驱还。如果進(jìn)程的CPU區(qū)間超過了一個時間片议蟆,那么該進(jìn)程就被搶占并放回就緒隊列咐容。
- 多級隊列調(diào)度算法:將就緒隊列分成多個獨立的隊列,每個隊列都有自己的調(diào)度算法路狮,隊列之間采用固定優(yōu)先級搶占調(diào)度奄妨。其中砸抛,一個進(jìn)程根據(jù)自身屬性被永久地分配到一個隊列中。
- 多級反饋隊列調(diào)度算法:與多級隊列調(diào)度算法相比锰悼,其允許進(jìn)程在隊列之間移動:若進(jìn)程使用過多CPU時間箕般,那么它會被轉(zhuǎn)移到更低的優(yōu)先級隊列丝里;在較低優(yōu)先級隊列等待時間過長的進(jìn)程會被轉(zhuǎn)移到更高優(yōu)先級隊列杯聚,以防止饑餓發(fā)生。
說一說進(jìn)程同步有哪幾種機(jī)制
原子操作颁褂、信號量機(jī)制颁独、自旋鎖管程伪冰、會合贮聂、分布式系統(tǒng)
什么是虛擬內(nèi)存?
內(nèi)存的發(fā)展歷程
沒有內(nèi)存抽象(單進(jìn)程歼冰,除去操作系統(tǒng)所用的內(nèi)存之外骄瓣,全部給用戶程序使用) —> 有內(nèi)存抽象(多進(jìn)程榕栏,進(jìn)程獨立的地址空間,交換技術(shù)(內(nèi)存大小不可能容納下所有并發(fā)執(zhí)行的進(jìn)程)
)—> 連續(xù)內(nèi)存分配(固定大小分區(qū)(多道程序的程度受限)庆揪,可變分區(qū)(首次適應(yīng)缸榛,最佳適應(yīng)内颗,最差適應(yīng))均澳,碎片) —> 不連續(xù)內(nèi)存分配(分段找前,分頁,段頁式项戴,虛擬內(nèi)存)
虛擬內(nèi)存
虛擬內(nèi)存允許執(zhí)行進(jìn)程不必完全在內(nèi)存中周叮。虛擬內(nèi)存的基本思想是:每個進(jìn)程擁有獨立的地址空間则吟,這個空間被分為大小相等的多個塊,稱為頁(Page)得糜,每個頁都是一段連續(xù)的地址朝抖。這些頁被映射到物理內(nèi)存谍珊,但并不是所有的頁都必須在內(nèi)存中才能運行程序砌滞。當(dāng)程序引用到一部分在物理內(nèi)存中的地址空間時,由硬件立刻進(jìn)行必要的映射绊茧;當(dāng)程序引用到一部分不在物理內(nèi)存中的地址空間時华畏,由操作系統(tǒng)負(fù)責(zé)將缺失的部分裝入物理內(nèi)存并重新執(zhí)行失敗的命令亡笑。這樣仑乌,對于進(jìn)程而言绝骚,邏輯上似乎有很大的內(nèi)存空間压汪,實際上其中一部分對應(yīng)物理內(nèi)存上的一塊(稱為幀止剖,通常頁和幀大小相等)穿香,還有一些沒加載在內(nèi)存中的對應(yīng)在硬盤上皮获,如下圖所示洒宝。
注意父能,請求分頁系統(tǒng)法竞、請求分段系統(tǒng)和請求段頁式系統(tǒng)都是針對虛擬內(nèi)存的薛躬,通過請求實現(xiàn)內(nèi)存與外存的信息置換。
由上圖可以看出呆细,虛擬內(nèi)存實際上可以比物理內(nèi)存大型宝。當(dāng)訪問虛擬內(nèi)存時八匠,會訪問MMU(內(nèi)存管理單元)去匹配對應(yīng)的物理地址(比如上圖的0,1趴酣,2)梨树。如果虛擬內(nèi)存的頁并不存在于物理內(nèi)存中(如上圖的3,4),會產(chǎn)生缺頁中斷岖寞,從磁盤中取得缺的頁放入內(nèi)存抡四,如果內(nèi)存已滿,還會根據(jù)某種算法將磁盤中的頁換出仗谆。
頁面置換算法
- FIFO先進(jìn)先出算法:在操作系統(tǒng)中經(jīng)常被用到指巡,比如作業(yè)調(diào)度(主要實現(xiàn)簡單,很容易想到);
- LRU(Least recently use)最近最少使用算法:根據(jù)使用時間到現(xiàn)在的長短來判斷瑰排;
- LFU(Least frequently use)最少使用次數(shù)算法:根據(jù)使用次數(shù)來判斷字逗;
- OPT(Optimal replacement)最優(yōu)置換算法:理論的最優(yōu)俭厚,理論;就是要保證置換出去的是不再被使用的頁,或者是在實際內(nèi)存中最晚使用的算法论寨。
虛擬內(nèi)存的應(yīng)用與優(yōu)點
虛擬內(nèi)存很適合在多道程序設(shè)計系統(tǒng)中使用火焰,許多程序的片段同時保存在內(nèi)存中。當(dāng)一個程序等待它的一部分讀入內(nèi)存時,可以把CPU交給另一個進(jìn)程使用。虛擬內(nèi)存的使用可以帶來以下好處:
- 在內(nèi)存中可以保留多個進(jìn)程,系統(tǒng)并發(fā)度提高
- 解除了用戶與內(nèi)存之間的緊密約束,進(jìn)程可以比內(nèi)存的全部空間還大
顛簸
顛簸本質(zhì)上是指頻繁的頁調(diào)度行為,具體來講,進(jìn)程發(fā)生缺頁中斷囊咏,這時葛家,必須置換某一頁末誓。然而殊校,其他所有的頁都在使用敬察,它置換一個頁,但又立刻再次需要這個頁。因此,會不斷產(chǎn)生缺頁中斷语泽,導(dǎo)致整個系統(tǒng)的效率急劇下降据过,這種現(xiàn)象稱為顛簸(抖動)鳞芙。
內(nèi)存顛簸的解決策略包括:
- 如果是因為頁面替換策略失誤,可以修改替換算法來解決這個問題;
- 如果是因為運行的程序太多,造成程序無法同時將所有頻繁訪問的頁面調(diào)入內(nèi)存敬鬓,則要降低多道程序的數(shù)量数尿;
- 否則,還剩下兩個辦法:終止該進(jìn)程或增加物理內(nèi)存容量。
局部性原理
- 時間上的局部性:最近被訪問的頁在不久的將來還會被訪問巩剖;
- 空間上的局部性:內(nèi)存中被訪問的頁周圍的頁也很可能被訪問断国。
END
喜歡的朋友記得點點贊和關(guān)注,支持下筆者莱坎,謝謝啦