《操作系统知识点整理》
目錄
- 進(jìn)程與線程比較
- 多線程
- 同步與互斥
- 生產(chǎn)者與消費(fèi)者
- 哲學(xué)家就餐問(wèn)題
- 讀者寫者問(wèn)題
- 進(jìn)程間通信
- 管道
- 消息隊(duì)列
- 共享內(nèi)存
- 信號(hào)量
- 信號(hào)
- Socket
- 鎖
- 互斥鎖與自旋鎖
- 讀寫鎖
- 樂(lè)觀鎖與悲觀鎖
- 死鎖
進(jìn)程與線程比較
- 進(jìn)程是資源(包括內(nèi)存、打開的文件等)分配的單位,線程是 CPU 調(diào)度的單位;
- 進(jìn)程擁有一個(gè)完整的資源平臺(tái),而線程只獨(dú)享必不可少的資源,如寄存器和棧;
- 線程同樣具有就緒、阻塞、執(zhí)行三種基本狀態(tài),同樣具有狀態(tài)之間的轉(zhuǎn)換關(guān)系;
- 線程能減少并發(fā)執(zhí)行的時(shí)間和空間開銷;
線程相比進(jìn)程能減少開銷,體現(xiàn)在:
- 線程的創(chuàng)建時(shí)間比進(jìn)程快,因?yàn)檫M(jìn)程在創(chuàng)建的過(guò)程中,還需要資源管理信息,比如內(nèi)存管理信息、文件管理信息,而線程在創(chuàng)建的過(guò)程中,不會(huì)涉及這些資源管理信息,而是共享它們;
- 線程的終止時(shí)間比進(jìn)程快,因?yàn)榫€程釋放的資源相比進(jìn)程少很多;
- 同一個(gè)進(jìn)程內(nèi)的線程切換比進(jìn)程切換快,因?yàn)榫€程具有相同的地址空間(虛擬內(nèi)存共享),這意味著同一個(gè)進(jìn)程的線程都具有同一個(gè)頁(yè)表,那么在切換的時(shí)候不需要切換頁(yè)表。而對(duì)于進(jìn)程之間的切換,切換的時(shí)候要把頁(yè)表給切換掉,而頁(yè)表的切換過(guò)程開銷是比較大的;
- 由于同一進(jìn)程的各線程間共享內(nèi)存和文件資源,那么在線程之間數(shù)據(jù)傳遞的時(shí)候,就不需要經(jīng)過(guò)內(nèi)核了,這就使得線程之間的數(shù)據(jù)交互效率更高了
多線程
同步與互斥
多個(gè)線程如果競(jìng)爭(zhēng)共享資源,如果不采取有效的措施,則會(huì)造成共享數(shù)據(jù)的混亂。
由于多線程執(zhí)行操作共享變量的這段代碼可能會(huì)導(dǎo)致競(jìng)爭(zhēng)狀態(tài),因此我們將此段代碼稱為臨界區(qū)(*critical section*),它是訪問(wèn)共享資源的代碼片段,一定不能給多線程同時(shí)執(zhí)行。
我們希望這段代碼是互斥(mutualexclusion)的,也就說(shuō)保證一個(gè)線程在臨界區(qū)執(zhí)行時(shí),其他線程應(yīng)該被阻止進(jìn)入臨界區(qū)
所謂同步,就是并發(fā)進(jìn)程/線程在一些關(guān)鍵點(diǎn)上可能需要互相等待與互通消息,這種相互制約的等待與互通信息稱為進(jìn)程/線程同步。
- 鎖:加鎖、解鎖操作;
- 信號(hào)量:P、V 操作;
這兩個(gè)都可以方便地實(shí)現(xiàn)進(jìn)程/線程互斥,而信號(hào)量比鎖的功能更強(qiáng)一些,它還可以方便地實(shí)現(xiàn)進(jìn)程/線程同步。
鎖分為無(wú)等待鎖與自旋鎖:
當(dāng)獲取不到鎖時(shí),線程就會(huì)一直 wile 循環(huán),不做任何事情,所以就被稱為「忙等待鎖」,也被稱為自旋鎖(*spin lock*)。
無(wú)等待鎖顧明思議就是獲取不到鎖的時(shí)候,不用自旋。
既然不想自旋,那當(dāng)沒獲取到鎖的時(shí)候,就把當(dāng)前線程放入到鎖的等待隊(duì)列,然后執(zhí)行調(diào)度程序,把 CPU 讓給其他線程執(zhí)行。
信號(hào)量表示資源的數(shù)量,對(duì)應(yīng)的變量是一個(gè)整型(sem)變量
- P 操作:將 sem 減 1,相減后,如果 sem < 0,則進(jìn)程/線程進(jìn)入阻塞等待,否則繼續(xù),表明 P 操作可能會(huì)阻塞;
- V 操作:將 sem 加 1,相加后,如果 sem <= 0,喚醒一個(gè)等待中的進(jìn)程/線程,表明 V 操作不會(huì)阻塞;
對(duì)于兩個(gè)并發(fā)線程,互斥信號(hào)量的值僅取 1、0 和 -1 三個(gè)值,分別表示:
如果互斥信號(hào)量為 1,表示沒有線程進(jìn)入臨界區(qū);
如果互斥信號(hào)量為 0,表示有一個(gè)線程進(jìn)入臨界區(qū);
如果互斥信號(hào)量為 -1,表示一個(gè)線程進(jìn)入臨界區(qū),另一個(gè)線程等待進(jìn)入。
通過(guò)互斥信號(hào)量的方式,就能保證臨界區(qū)任何時(shí)刻只有一個(gè)線程在執(zhí)行,就達(dá)到了互斥的效果。
生產(chǎn)者與消費(fèi)者
- 生產(chǎn)者在生成數(shù)據(jù)后,放在一個(gè)緩沖區(qū)中;
- 消費(fèi)者從緩沖區(qū)取出數(shù)據(jù)處理;
- 任何時(shí)刻,只能有一個(gè)生產(chǎn)者或消費(fèi)者可以訪問(wèn)緩沖區(qū);
- 任何時(shí)刻只能有一個(gè)線程操作緩沖區(qū),說(shuō)明操作緩沖區(qū)是臨界代碼,需要互斥;
- 緩沖區(qū)空時(shí),消費(fèi)者必須等待生產(chǎn)者生成數(shù)據(jù);緩沖區(qū)滿時(shí),生產(chǎn)者必須等待消費(fèi)者取出數(shù)據(jù)。說(shuō)明生產(chǎn)者和消費(fèi)者需要同步。
我們需要三個(gè)信號(hào)量 :
互斥信號(hào)量 mutex:用于互斥訪問(wèn)緩沖區(qū),初始化值為 1
資源信號(hào)量 fullBuffers:用于消費(fèi)者詢問(wèn)緩沖區(qū)是否有數(shù)據(jù),有數(shù)據(jù)則讀取數(shù)據(jù),初始化值為 0(表明緩沖區(qū)一開始為空);
資源信號(hào)量 emptyBuffers:用于生產(chǎn)者詢問(wèn)緩沖區(qū)是否有空位,有空位則生成數(shù)據(jù),初始化值為 n (緩沖區(qū)大小);
哲學(xué)家就餐問(wèn)題
- 5 個(gè)老大哥哲學(xué)家,閑著沒事做,圍繞著一張圓桌吃面;
- 巧就巧在,這個(gè)桌子只有 5 支叉子,每?jī)蓚€(gè)哲學(xué)家之間放一支叉子;
- 哲學(xué)家圍在一起先思考,思考中途餓了就會(huì)想進(jìn)餐;
- 奇葩的是,這些哲學(xué)家要兩支叉子才愿意吃面,也就是需要拿到左右兩邊的叉子才進(jìn)餐;
- 吃完后,會(huì)把兩支叉子放回原處,繼續(xù)思考;
那么問(wèn)題來(lái)了,如何保證哲 學(xué)家們的動(dòng)作有序進(jìn)行,而不會(huì)出現(xiàn)有人永遠(yuǎn)拿不到叉子呢?
讓偶數(shù)編號(hào)的哲學(xué)家「先拿左邊的叉子后拿右邊的叉子」,奇數(shù)編號(hào)的哲學(xué)家「先拿右邊的叉子后拿左邊的叉子」
上面的程序,在 P 操作時(shí),根據(jù)哲學(xué)家的編號(hào)不同,拿起左右兩邊叉子的順序不同。另外,V 操作是不需要分支的,因?yàn)?V 操作是不會(huì)阻塞的。
讀者寫者問(wèn)題
讀者只會(huì)讀取數(shù)據(jù),不會(huì)修改數(shù)據(jù),而寫者即可以讀也可以修改數(shù)據(jù)。
不談讀優(yōu)先于寫優(yōu)先鎖,直接談公平讀寫鎖。
公平策略 :
開始來(lái)了一些讀者讀數(shù)據(jù),它們?nèi)窟M(jìn)入讀者隊(duì)列,此時(shí)來(lái)了一個(gè)寫者,執(zhí)行 P(falg) 操作,使得后續(xù)到來(lái)的讀者都阻塞在 flag 上,不能進(jìn)入讀者隊(duì)列,這會(huì)使得讀者隊(duì)列逐漸為空,即 rCount 減為 0。
這個(gè)寫者也不能立馬開始寫(因?yàn)榇藭r(shí)讀者隊(duì)列不為空),會(huì)阻塞在信號(hào)量 wDataMutex 上,讀者隊(duì)列中的讀者全部讀取結(jié)束后,最后一個(gè)讀者進(jìn)程執(zhí)行 V(wDataMutex),喚醒剛才的寫者,寫者則繼續(xù)開始進(jìn)行寫操作。
為此時(shí)讀者隊(duì)列不為空),會(huì)阻塞在信號(hào)量 wDataMutex 上,讀者隊(duì)列中的讀者全部讀取結(jié)束后,最后一個(gè)讀者進(jìn)程執(zhí)行 V(wDataMutex),喚醒剛才的寫者,寫者則繼續(xù)開始進(jìn)行寫操作。
進(jìn)程間通信
每個(gè)進(jìn)程的用戶地址空間都是獨(dú)立的,一般而言是不能互相訪問(wèn)的,但內(nèi)核空間是每個(gè)進(jìn)程都共享的,所以進(jìn)程之間要通信必須通過(guò)內(nèi)核。
管道
管道傳輸數(shù)據(jù)是單向的,如果想相互通信,我們需要?jiǎng)?chuàng)建兩個(gè)管道才行。
匿名管道,用完了就銷毀。
命名管道,也被叫做 FIFO,因?yàn)閿?shù)據(jù)是先進(jìn)先出的傳輸方式
只有當(dāng)管道里的數(shù)據(jù)被讀完后,命令才可以正常退出。
管道這種通信方式效率低,不適合進(jìn)程間頻繁地交換數(shù)據(jù)。當(dāng)然,它的好處,自然就是簡(jiǎn)單,同時(shí)也我們很容易得知管道里的數(shù)據(jù)已經(jīng)被另一個(gè)進(jìn)程讀取了。
對(duì)于匿名管道,它的通信范圍是存在父子關(guān)系的進(jìn)程。因?yàn)楣艿罌]有實(shí)體,也就是沒有管道文件,只能通過(guò) fork 來(lái)復(fù)制父進(jìn)程 fd 文件描述符,來(lái)達(dá)到通信的目的。
對(duì)于命名管道,它可以在不相關(guān)的進(jìn)程間也能相互通信。因?yàn)槊罟艿?#xff0c;提前創(chuàng)建了一個(gè)類型為管道的設(shè)備文件,在進(jìn)程里只要使用這個(gè)設(shè)備文件,就可以相互通信。
消息隊(duì)列
A 進(jìn)程要給 B 進(jìn)程發(fā)送消息,A 進(jìn)程把數(shù)據(jù)放在對(duì)應(yīng)的消息隊(duì)列后就可以正常返回了,B 進(jìn)程需要的時(shí)候再去讀取數(shù)據(jù)就可以了。
消息隊(duì)列是保存在內(nèi)核中的消息鏈表,在發(fā)送數(shù)據(jù)時(shí),會(huì)分成一個(gè)一個(gè)獨(dú)立的數(shù)據(jù)單元,也就是消息體(數(shù)據(jù)塊),消息體是用戶自定義的數(shù)據(jù)類型,消息的發(fā)送方和接收方要約定好消息體的數(shù)據(jù)類型,所以每個(gè)消息體都是固定大小的存儲(chǔ)塊,不像管道是無(wú)格式的字節(jié)流數(shù)據(jù)。如果進(jìn)程從消息隊(duì)列中讀取了消息體,內(nèi)核就會(huì)把這個(gè)消息體刪除。
消息隊(duì)列不適合比較大數(shù)據(jù)的傳輸,因?yàn)樵趦?nèi)核中每個(gè)消息體都有一個(gè)最大長(zhǎng)度的限制,同時(shí)所有隊(duì)列所包含的全部消息體的總長(zhǎng)度也是有上限。
消息隊(duì)列通信過(guò)程中,存在用戶態(tài)與內(nèi)核態(tài)之間的數(shù)據(jù)拷貝開銷,因?yàn)檫M(jìn)程寫入數(shù)據(jù)到內(nèi)核中的消息隊(duì)列時(shí),會(huì)發(fā)生從用戶態(tài)拷貝數(shù)據(jù)到內(nèi)核態(tài)的過(guò)程,同理另一進(jìn)程讀取內(nèi)核中的消息數(shù)據(jù)時(shí),會(huì)發(fā)生從內(nèi)核態(tài)拷貝數(shù)據(jù)到用戶態(tài)的過(guò)程。
共享內(nèi)存
共享內(nèi)存的機(jī)制,就是拿出一塊虛擬地址空間來(lái),映射到相同的物理內(nèi)存中。
這樣這個(gè)進(jìn)程寫入的東西,另外一個(gè)進(jìn)程馬上就能看到了,都不需要拷貝來(lái)拷貝去,傳來(lái)傳去,大大提高了進(jìn)程間通信的速度。
信號(hào)量
了防止多進(jìn)程競(jìng)爭(zhēng)共享資源,而造成的數(shù)據(jù)錯(cuò)亂,所以需要保護(hù)機(jī)制,使得共享的資源,在任意時(shí)刻只能被一個(gè)進(jìn)程訪問(wèn)。正好,信號(hào)量就實(shí)現(xiàn)了這一保護(hù)機(jī)制。
信號(hào)量其實(shí)是一個(gè)整型的計(jì)數(shù)器,主要用于實(shí)現(xiàn)進(jìn)程間的互斥與同步,而不是用于緩存進(jìn)程間通信的數(shù)據(jù)。
控制信號(hào)量的方式有兩種原子操作 :
一個(gè)是 P 操作,這個(gè)操作會(huì)把信號(hào)量減去 -1,相減后如果信號(hào)量 < 0,則表明資源已被占用,進(jìn)程需阻塞等待;相減后如果信號(hào)量 >= 0,則表明還有資源可使用,進(jìn)程可正常繼續(xù)執(zhí)行。
另一個(gè)是 V 操作,這個(gè)操作會(huì)把信號(hào)量加上 1,相加后如果信號(hào)量 <= 0,則表明當(dāng)前有阻塞中的進(jìn)程,于是會(huì)將該進(jìn)程喚醒運(yùn)行;相加后如果信號(hào)量 > 0,則表明當(dāng)前沒有阻塞中的進(jìn)程;
P 操作是用在進(jìn)入共享資源之前,V 操作是用在離開共享資源之后,這兩個(gè)操作是必須成對(duì)出現(xiàn)的 。
兩個(gè)進(jìn)程互斥訪問(wèn)共享內(nèi)存,我們可以初始化信號(hào)量為 1。
進(jìn)程 A 在訪問(wèn)共享內(nèi)存前,先執(zhí)行了 P 操作,由于信號(hào)量的初始值為 1,故在進(jìn)程 A 執(zhí)行 P 操作后信號(hào)量變?yōu)?0,表示共享資源可用,于是進(jìn)程 A 就可以訪問(wèn)共享內(nèi)存。
若此時(shí),進(jìn)程 B 也想訪問(wèn)共享內(nèi)存,執(zhí)行了 P 操作,結(jié)果信號(hào)量變?yōu)榱?-1,這就意味著臨界資源已被占用,因此進(jìn)程 B 被阻塞。
直到進(jìn)程 A 訪問(wèn)完共享內(nèi)存,才會(huì)執(zhí)行 V 操作,使得信號(hào)量恢復(fù)為 0,接著就會(huì)喚醒阻塞中的線程 B,使得進(jìn)程 B 可以訪問(wèn)共享內(nèi)存,最后完成共享內(nèi)存的訪問(wèn)后,執(zhí)行 V 操作,使信號(hào)量恢復(fù)到初始值 1。
信號(hào)初始化為 1,就代表著是互斥信號(hào)量,它可以保證共享內(nèi)存在任何時(shí)刻只有一個(gè)進(jìn)程在訪問(wèn),這就很好的保護(hù)了共享內(nèi)存。
進(jìn)程 A 是負(fù)責(zé)生產(chǎn)數(shù)據(jù),而進(jìn)程 B 是負(fù)責(zé)讀取數(shù)據(jù),這兩個(gè)進(jìn)程是相互合作、相互依賴的,進(jìn)程 A 必須先生產(chǎn)了數(shù)據(jù),進(jìn)程 B 才能讀取到數(shù)據(jù),所以執(zhí)行是有前后順序的。
信號(hào)量來(lái)實(shí)現(xiàn)多進(jìn)程同步的方式,我們可以初始化信號(hào)量為 0。
如果進(jìn)程 B 比進(jìn)程 A 先執(zhí)行了,那么執(zhí)行到 P 操作時(shí),由于信號(hào)量初始值為 0,故信號(hào)量會(huì)變?yōu)?-1,表示進(jìn)程 A 還沒生產(chǎn)數(shù)據(jù),于是進(jìn)程 B 就阻塞等待;
接著,當(dāng)進(jìn)程 A 生產(chǎn)完數(shù)據(jù)后,執(zhí)行了 V 操作,就會(huì)使得信號(hào)量變?yōu)?0,于是就會(huì)喚醒阻塞在 P 操作的進(jìn)程 B;
最后,進(jìn)程 B 被喚醒后,意味著進(jìn)程 A 已經(jīng)生產(chǎn)了數(shù)據(jù),于是進(jìn)程 B 就可以正常讀取數(shù)據(jù)了。
信號(hào)
對(duì)于異常情況下的工作模式,就需要用「信號(hào)」的方式來(lái)通知進(jìn)程。
信號(hào)是進(jìn)程間通信機(jī)制中唯一的異步通信機(jī)制,因?yàn)榭梢栽谌魏螘r(shí)候發(fā)送信號(hào)給某一進(jìn)程,一旦有信號(hào)產(chǎn)生,我們就有下面這幾種,用戶進(jìn)程對(duì)信號(hào)的處理方式。
用戶進(jìn)程對(duì)信號(hào)的處理方式 :
1.執(zhí)行默認(rèn)操作。
2.捕捉信號(hào)。 為信號(hào)定義一個(gè)信號(hào)處理函數(shù)。當(dāng)信號(hào)發(fā)生時(shí),我們就執(zhí)行相應(yīng)的信號(hào)處理函數(shù)
3.忽略信號(hào)
Socket
跨網(wǎng)絡(luò)與不同主機(jī)上的進(jìn)程之間通信,就需要 Socket 通信了。
鎖
互斥鎖與自旋鎖
加鎖的目的就是保證共享資源在任意時(shí)間里,只有一個(gè)線程訪問(wèn),這樣就可以避免多線程導(dǎo)致共享數(shù)據(jù)錯(cuò)亂的問(wèn)題。
-
互斥鎖加鎖失敗后,線程會(huì)釋放 CPU ,給其他線程;
-
自旋鎖加鎖失敗后,線程會(huì)忙等待,直到它拿到鎖;
互斥鎖是一種「獨(dú)占鎖」,比如當(dāng)線程 A 加鎖成功后,此時(shí)互斥鎖已經(jīng)被線程 A 獨(dú)占了,只要線程 A 沒有釋放手中的鎖,線程 B 加鎖就會(huì)失敗,于是就會(huì)釋放 CPU 讓給其他線程,既然線程 B 釋放掉了 CPU,自然線程 B 加鎖的代碼就會(huì)被阻塞。
互斥鎖加鎖失敗時(shí),會(huì)從用戶態(tài)陷入到內(nèi)核態(tài),讓內(nèi)核幫我們切換線程,雖然簡(jiǎn)化了使用鎖的難度,但是存在一定的性能開銷成本。 會(huì)有兩次線程上下文切換的成本 。
如果你能確定被鎖住的代碼執(zhí)行時(shí)間很短,就不應(yīng)該用互斥鎖,而應(yīng)該選用自旋鎖,否則使用互斥鎖。
自旋鎖 在「用戶態(tài)」完成加鎖和解鎖操作,不會(huì)主動(dòng)產(chǎn)生線程上下文切換,所以相比互斥鎖來(lái)說(shuō),會(huì)快一些,開銷也小一些 。
使用自旋鎖的時(shí)候,當(dāng)發(fā)生多線程競(jìng)爭(zhēng)鎖的情況,加鎖失敗的線程會(huì)「忙等待」,直到它拿到鎖。
自旋鎖是最比較簡(jiǎn)單的一種鎖,一直自旋,利用 CPU 周期,直到鎖可用。需要注意,在單核 CPU 上,需要搶占式的調(diào)度器(即不斷通過(guò)時(shí)鐘中斷一個(gè)線程,運(yùn)行其他線程)。否則,自旋鎖在單 CPU 上無(wú)法使用,因?yàn)橐粋€(gè)自旋的線程永遠(yuǎn)不會(huì)放棄 CPU。
讀寫鎖
讀寫鎖適用于能明確區(qū)分讀操作和寫操作的場(chǎng)景。
讀寫鎖從字面意思我們也可以知道,它由「讀鎖」和「寫鎖」兩部分構(gòu)成,如果只讀取共享資源用「讀鎖」加鎖,如果要修改共享資源則用「寫鎖」加鎖。
讀寫鎖的工作原理是:
當(dāng)「寫鎖」沒有被線程持有時(shí),多個(gè)線程能夠并發(fā)地持有讀鎖。
但是,一旦「寫鎖」被線程持有后,讀線程的獲取讀鎖的操作會(huì)被阻塞,而且其他寫線程的獲取寫鎖的操作也會(huì)被阻塞。
讀寫鎖在讀多寫少的場(chǎng)景,能發(fā)揮出優(yōu)勢(shì)。
讀寫鎖可以分為「讀優(yōu)先鎖」和「寫優(yōu)先鎖」。
「讀優(yōu)先鎖」
當(dāng)讀線程 A 先持有了讀鎖,寫線程 B 在獲取寫鎖的時(shí)候,會(huì)被阻塞,并且在阻塞過(guò)程中,后續(xù)來(lái)的讀線程 C 仍然可以成功獲取讀鎖,最后直到讀線程 A 和 C 釋放讀鎖后,寫線程 B 才可以成功獲取寫鎖。
「寫優(yōu)先鎖」
當(dāng)讀線程 A 先持有了讀鎖,寫線程 B 在獲取寫鎖的時(shí)候,會(huì)被阻塞,并且在阻塞過(guò)程中,后續(xù)來(lái)的讀線程 C 獲取讀鎖時(shí)會(huì)失敗,于是讀線程 C 將被阻塞在獲取讀鎖的操作,這樣只要讀線程 A 釋放讀鎖后,寫線程 B 就可以成功獲取讀鎖。
「公平讀寫鎖」
公平讀寫鎖比較簡(jiǎn)單的一種方式是:用隊(duì)列把獲取鎖的線程排隊(duì),不管是寫線程還是讀線程都按照先進(jìn)先出的原則加鎖即可,這樣讀線程仍然可以并發(fā),也不會(huì)出現(xiàn)「饑餓」的現(xiàn)象。
樂(lè)觀鎖與悲觀鎖
互斥鎖、自旋鎖、讀寫鎖,都是屬于悲觀鎖 。
悲觀鎖做事比較悲觀,它認(rèn)為多線程同時(shí)修改共享資源的概率比較高,于是很容易出現(xiàn)沖突,所以訪問(wèn)共享資源前,先要上鎖。
那相反的,如果多線程同時(shí)修改共享資源的概率比較低,就可以采用樂(lè)觀鎖。
樂(lè)觀鎖做事比較樂(lè)觀,它假定沖突的概率很低,它的工作方式是:先修改完共享資源,再驗(yàn)證這段時(shí)間內(nèi)有沒有發(fā)生沖突,如果沒有其他線程在修改資源,那么操作完成,如果發(fā)現(xiàn)有其他線程已經(jīng)修改過(guò)這個(gè)資源,就放棄本次操作。
樂(lè)觀鎖全程并沒有加鎖,所以它也叫無(wú)鎖編程。
只有在沖突概率非常低,且加鎖成本非常高的場(chǎng)景時(shí),才考慮使用樂(lè)觀鎖。
死鎖
當(dāng)線程A持有一個(gè)資源A,正在等待獲取資源B;而線程B持有資源B,卻在等待獲取資源A,死鎖就產(chǎn)生了。
產(chǎn)生條件:
- 互斥:多個(gè)線程對(duì)于需要的資源進(jìn)行互斥的訪問(wèn)(生產(chǎn)者和消費(fèi)者競(jìng)爭(zhēng)一個(gè)mutex鎖)
- 非搶占:線程在競(jìng)爭(zhēng)到資源后,不能被搶占(消費(fèi)者搶到mutex,迫使生產(chǎn)者等待)
- 持有并等待:線程在競(jìng)爭(zhēng)中持有了資源,同時(shí)有在等待其他資源。(消費(fèi)者獲得mutex鎖后,等待生產(chǎn)者的sem_post(¬_empty))
- 環(huán)路等待:線程之間存在一個(gè)環(huán)路,環(huán)路上每個(gè)線程都負(fù)責(zé)控制一個(gè)資源,但這個(gè)資源又是下一個(gè)線程所要申請(qǐng)的。
方法一 . 破壞互斥條件
如果我們能在兩個(gè)線程跑之前,能給每個(gè)線程單獨(dú)拷貝一份資源AB的副本,就能有效的避免死鎖了 。
方法二. 破壞環(huán)路等待條件
可以強(qiáng)制規(guī)定任何線程取資源的順序只能是 “先取A再取B”的話,就能避免死鎖了 .
方法三.破壞不剝奪條件
除非線程自己還資源,否則線程會(huì)一直占有資源,是形成不可剝奪條件的原因 。 可以通過(guò)設(shè)置一個(gè)”最長(zhǎng)占用時(shí)間“的閾值來(lái)解決這個(gè)問(wèn)題 。如果過(guò)了10分鐘仍然沒有進(jìn)入下一個(gè)步驟,則歸還已有的資源。
方法四.破壞請(qǐng)求和保持條件
這里我們可以通過(guò)規(guī)定在任何情況下,一個(gè)線程獲取一個(gè)資源之后,必須歸還了資源之后才能請(qǐng)求另一個(gè)資源,就可以有效解決這個(gè)問(wèn)題。
總結(jié)
以上是生活随笔為你收集整理的《操作系统知识点整理》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 飞机票退票扣多少钱啊?
- 下一篇: HDU计算机网络系统2021复习提纲