操作系統【二】死鎖問題以及處理方法

死鎖的概念

  • 死鎖:在并發環境下,個進程因為競爭資源而造成的一種互相等待對方手里的資源,導致各進程都阻塞,無法向前推進的現象。

在這里插入圖片描述區別:

  • 饑餓:由于長期得不到想要的資源進程無法向前推進的現象。
  • 死循環:程序運行無法停止的狀態。
    在這里插入圖片描述

死鎖產生的必要條件

  • 互斥條件:資源是互斥使用的,只能被有限進程同時使用。(像內存、揚聲器這樣的資源不會發生死鎖)
  • 不剝奪條件:進程所獲得的資源在未使用完之前不能由其他進程奪走,只能主動釋放。
  • 請求和保持條件:進程已經保持了至少一個資源,但是又提出請求新的資源,當無法獲取新資源的時候阻塞,保持已經占有的資源不放。
  • 循環等待:存在一種進程資源的循環等待鏈,鏈中的每一個進程以獲得的資源同時被下一個進程請求。循環等待不一定會發生死鎖,但是死鎖一定會有循環等待現象發生。

需要注意的是上述條件都是必要條件。如果同類資源數大于1,則有循環等待也未必發生死鎖,但是如果每個資源只有一個的,那么循環等待就是死鎖的充分必要條件。

死鎖產生的時期

  • 對不可剝奪系統資源的競爭
  • 進程推進順序非法
  • 信號量使用不當

死鎖的處理策略

  • 預防死鎖:破壞死鎖產生的四個必要條件中的一個或者幾個
  • 避免死鎖:用某種方法防止系統進入不安全感的狀態,從而避免死鎖(例如銀行家算法)
  • 死鎖的檢測和解除:允許死鎖的發生,如果檢測發生后需要進行解除

預防死鎖

破壞互斥條件

將互斥使用的資源改造為允許共享使用的資源。

例如:SPOOLing技術。操作系統可以采用SPOOLing技術把獨占設備在邏輯上改造成共享設備。使用的方法就是增加了一個專門用于調度專用資源的進程。這樣對于其他進程來講自己的進程就立馬被處理了,而不會造成阻塞。

缺點:并不是所有的資源都可以改造成共享使用的資源,為了系統安全,許多地方必須保護這種互斥性,因此很多時候我們無法破壞這種互斥性。

破壞不剝奪條件

方案一:當某個進程請求新的資源得不到滿足時,他必須釋放所保持的所有資源,待以后需要的時候再主動申請。(即使自己還沒有使用結束)

方案二:當某個進程需要使用被占用的資源的時候,可以由操作系統協助將想要的資源強制剝奪。這種方式一般需要考慮各進程的優先級。

缺點:

  • 實現起來比較復雜
  • 釋放已經獲得的資源可能造成前一段工作的失效。因此這種方法一般只適用于已保存和恢復的資源,例如CPU。
  • 反復的申請和釋放資源會增加系統開銷,降低系統吞吐量。
  • 采用方案一的話如果得不到某個資源則之前的資源都需要放棄,以后再重新申請,這樣有可能導致進程的饑餓。
破壞請求和保持條件
  • 靜態分配方法:在進程運行前一次申請完它所需要的全部進程,在他的資源未滿足前不讓他投入運行,一旦投入運行后這些資源就一直歸他所有。

實現簡單。缺點明顯:資源利用率極低,而且可能導致某些進程饑餓。

破壞循環等待條件
  • 順序資源分配法:首先給系統中的資源編號,規定每個進程必須按照編號遞增的順序請求資源,同類資源(編號相同的資源)一次性申請完。
    原理分析:只有擁有小編號資源的進程等待大編號資源,而不會有擁有大編號資源的進程等待小編號資源,從而防止了循環等待現象的發生。

在這里插入圖片描述

缺點:

  • 不方便增加新的設備,因為可能需要重新分配編號
  • 進程實際使用資源的順序可能和編號遞增的順序不一樣從而導致資源的浪費。如果想要解決這個問題,就必須按照規定次序申請資源,用戶編程麻煩。

避免死鎖

安全序列:如果系統按照安全序列分配資源,則每個進程都能夠順利完成。只要能和造出一個安全序列,系統就是安全狀態。當然安全狀態可能有多個。
如果分配了資源以后,系統找不出任何一個安全序列,則系統進入不安全狀態。這就意味著之后可能所有進程都無法順利執行下去。當然,如果有進程提前歸還了一些資源,則系統也有可能重新回到安全狀態。
如果系統處于安全狀態,就一定不會發生死鎖。如果系統進入不安全狀態,就可能發生死鎖(處于不安全狀態未必就是發生了死鎖。但是發生死鎖一定是在不安全狀態)

因此可以在資源分配之前與預先判斷分配是否會導致系統進入不安全狀態,以此決定是否答應資源分配請求。

銀行家算法

核心思想:在進程提出資源申請時,先預判此次分配是否會導致系統進入不安全狀態。如果會進入不安全狀態,就暫時不答應這次請求,讓該進程先被阻塞等待。

在這里插入圖片描述數據結構:

  • 長度為m的一維數組Available表示還有多少可用資源
  • n*m矩陣Max表示各個進程對資源的最大需求數
  • n*m矩陣Allocation表示已經給個進程分配了多少資源
  • n*m矩陣Need表示各進程還需要多少資源
  • 長度為m的一維數組Request表示進程此次申請的各種資源數

銀行家算法步驟:

  • 檢查此次申請是否超過了最大需求數
  • 檢查此時系統剩余的可用資源是否還能滿足這次請求
  • 試探著分配,更改各數據結構(Available Allocation Need
  • 用安全性算法檢查此次分配是否會導致系統進入不安全狀態

安全性算法步驟:

  • 檢查當前剩余可用資源能否滿足某個進程的最大需求,如果可以,就將該進程加入安全序列,并把該進程持有的資源全部回收
  • 不斷重復上述過程,檢查最終能否將所有進程都加入安全序列

死鎖的檢測和解除

如果不采取預防思索的措施,也不采取避免死鎖的措施,系統很有可能發生死鎖。這個時候就應該進行死鎖的檢測和解除。

死鎖的檢測

資源分配圖
在這里插入圖片描述
如果系統中剩余的可用資源足夠滿足進程的需求,那么這個進程是不會阻塞的,可以順利執行下去。執行結束后消除與該進程相連的所有邊(歸還資源)。

如果按照上述過程最終能夠消除所有邊,則稱這個圖是可完全簡化的。此時一定沒有發生死鎖。(相當于找到一個安全序列)

如果不能消除所有邊,那么此時就是發生了死鎖。

檢測死鎖的算法:

  • 在資源分配圖中,找出既不阻塞又不是孤點的進程,消去它所有的請求邊和分配邊,使之成為孤立的節點。
  • 重復上面的過程,直至資源分配圖變成可完全簡化的。

死鎖定理:如果某時刻的資源分配圖是不可完全簡化的,那么此時可系統死鎖。

死鎖的解除

并不是系統中所有進程都是死鎖狀態,用死鎖檢測算法化簡資源分配圖以后,還連著邊的那些進程就是死鎖進程。
解除死鎖的主要方法有:

  • 資源剝奪法。掛起(暫時放到外存上)某些死鎖進程,并搶占它的資源,將這些資源分配給其他死鎖進程。但是應該防止被掛起的進程長時間得不到資源而饑餓。
  • 撤銷進程法(終止進程法)。強制撤銷部分、甚至全部死鎖的進程,并剝奪這些進程的資源。實現簡單,代價較大。
  • 進程回退法:讓一個或者多個死鎖進程回退到可以避免死鎖的地步。這就要求系統記錄進程的歷史信息,設置還原點。

應該奪取哪個進程的資源:

  • 進程優先級
  • 已執行時間
  • 還有多久能夠完成
  • 進程已經使用了多少資源
  • 進程是交互式的還是批處理式的(優先犧牲批處理)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383682.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383682.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383682.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux網絡編程——I/O復用之poll函數

https://blog.csdn.net/lianghe_work/article/details/46534029一、回顧前面的selectselect優點:目前幾乎在所有的平臺上支持,其良好跨平臺支持也是它的一個優點select缺點:1.每次調用 select(),都需要把 fd 集合從用戶態拷貝到內…

操作系統【一】進程同步和信號量

基本概念 進程異步性特征:各并發執行的進程以各自獨立的,不可預知的速度向前推進。 進程同步又稱作直接制約關系,他是指為完成某種任務而建立的兩個或者多個進程,這些進程因為需要在某些位置上協調他們的工作順序而產生的制約關…

計算機網絡【四】數據鏈路層基本概念+點到點通信(PPP協議)

數據鏈路層基本概念 路由器是網絡層設備 數據鏈路層:數據管道,傳輸的是數據包加上發送地址,接收地址,校驗的數據幀 數據鏈路層的信道類型: 點到點信道:使用一對一的點到點通信方式(兩個設備…

Linux網絡編程——tcp并發服務器(poll實現)

https://blog.csdn.net/lianghe_work/article/details/46535859想詳細徹底地了解poll或看懂下面的代碼請參考《Linux網絡編程——I/O復用之poll函數》 代碼&#xff1a;#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#…

二分查找的最大比較次數

二分查找很簡單&#xff0c;可是對于一個區間長度為n的數組&#xff0c;最大的比較次數為多少呢&#xff1f; 對于標準的二分查找&#xff0c;我們每次從區間[l,r)中取一個值&#xff0c;和中間值mid(lr)>>1進行比較&#xff0c;然后將數組分為[l,mid) [mid1,r)&#xf…

Linux網絡編程——I/O復用函數之epoll

https://blog.csdn.net/lianghe_work/article/details/46544567一、epoll概述epoll 是在 2.6 內核中提出的&#xff0c;是之前的 select() 和 poll() 的增強版本。相對于 select() 和 poll() 來說&#xff0c;epoll 更加靈活&#xff0c;沒有描述符限制。epoll 使用一個文件描述…

操作系統【三】內存管理基礎+連續內存分配

內存的基礎知識 內存分為按字節編址&#xff08;8位&#xff09;和字編制&#xff08;不同計算機不一樣&#xff0c;64位計算機就是64位&#xff0c;即8個字節&#xff09; 相對地址邏輯地址 絕對地址物理地址 從邏輯地址到物理地址的轉換由裝入解決。 裝入的三種方式 絕對…

MSG_PEEK標志

https://blog.csdn.net/aspnet_lyc/article/details/28937229 MSG_PEEK標志可以用來讀取套接字接收隊列中可讀的數據&#xff0c;一些情況會用到它&#xff0c;比如為了避免不阻塞而先檢查套接字接收隊列中可讀的數據長度&#xff0c;再采取相應操作。當然&#xff0c;不阻塞也…

快速排序詳解+各種實現方式

快速排序的思想大體來說比較簡單&#xff0c;就是從數組中挑選一個數字當做樞紐&#xff0c;然后將比樞紐大的和比樞紐小的分別放在樞紐的兩邊&#xff0c;再遞歸地對兩邊進行操作&#xff0c;從而進行分治解決問題。平均情況下快速排序是復雜度為O(nlogn)O(nlogn)O(nlogn)&…

C++的單例模式與線程安全單例模式(懶漢/餓漢)

https://www.cnblogs.com/qiaoconglovelife/p/5851163.html1 教科書里的單例模式我們都很清楚一個簡單的單例模式該怎樣去實現&#xff1a;構造函數聲明為private或protect防止被外部函數實例化&#xff0c;內部保存一個private static的類指針保存唯一的實例&#xff0c;實例的…

計算矩陣的逆和行列式的值(高斯消元+LU分解)

計算矩陣的逆 選主元的高斯消元法 樸素的高斯消元法是將矩陣A和單位矩陣放在一起&#xff0c;通過行操作&#xff08;或者列操作&#xff09;將A變為單位矩陣&#xff0c;這個時候單位矩陣就是矩陣A的逆矩陣。從上到下將A變為上三角矩陣的復雜度為O(n3n^3n3)&#xff0c;再從下…

Linux網絡編程——tcp并發服務器(epoll實現)

https://blog.csdn.net/lianghe_work/article/details/46551871通過epoll實現tcp并發回執服務器&#xff08;客戶端給服務器發啥&#xff0c;服務器就給客戶端回啥&#xff09; 代碼如下&#xff1a;#include <string.h>#include <stdio.h>#include <stdlib.h&g…

證明AVL樹的上界和下界

對于n個節點的AVL樹&#xff0c;其高度最低的時候肯定為葉子節點只在最后一層和倒數第二層的時候。即對于2k?1<n≦2k1?12^k-1< n\leqq 2^{k1}-12k?1<n≦2k1?1的時候下界都為kkk。因此下界為h┌log2(n1)┐?1h\ulcorner log_2(n1)\urcorner-1h┌log2?(n1)┐?1 對…

淺談dup和dup2的用法

https://blog.csdn.net/u012058778/article/details/78705536一、dup和dup2函數 這兩個函數都可以來復制一個現有的文件描述符&#xff0c;他們的聲明如下&#xff1a;#include <unistd.h>int dup(int fd);int dup2(int fd, int fd 2); 123 關于dup函數&#xff0c;當我…

C++ cin 實現循環讀入

習慣了使用while(~scanf("%d",x)){}來實現循環讀入&#xff0c;但是有時候使用泛型編程的時候就必須使用C中的cin&#xff0c;但是當我想要實現循環讀入的時候卻發現有些困難。 我們可以看一下下面這個簡單的例子&#xff1a; #include <iostream>using name…

BFPTR算法詳解+實現+復雜度證明

BFPTR算法是由Blum、Floyed、Pratt、Tarjan、Rivest這五位牛人一起提出來的&#xff0c;其特點在于可以以最壞復雜度為O(n)O(n)O(n)地求解top?ktop-ktop?k問題。所謂top?ktop-ktop?k問題就是從一個序列中求解其第k大的問題。 top?ktop-ktop?k問題有許多解決方法&#xff…

C++子類對象隱藏了父類的同名成員函數(隱藏篇)

https://blog.csdn.net/alpha_love/article/details/75222175#include <iostream>#include <stdlib.h>#include <string>using namespace std;/*** 定義人類: Person* 數據成員: m_strName* 成員函數: attack()*/class Person{public:Person(){cout<<&…

隨機化快速排序+快速選擇 復雜度證明+運行測試

對于快速排序和快速選擇我之前的文章已經有詳細的說明&#xff0c;需要了解的同學可以移步 傳送門&#xff1a;快速排序&#xff5c;快速選擇(BFPTR) 所謂隨機化其實就是選擇樞紐的時候使用隨機數選擇而已&#xff0c;實現起來很簡單。但是我們使用隨機數如何保證復雜度呢&am…

C++子類父類成員函數的覆蓋和隱藏實例詳解

https://www.jb51.net/article/117380.htm函數的覆蓋覆蓋發生的條件&#xff1a; &#xff08;1&#xff09; 基類必須是虛函數&#xff08;使用virtual 關鍵字來進行聲明&#xff09; &#xff08;2&#xff09;發生覆蓋的兩個函數分別位于派生類和基類 &#xff08;3&#xf…

【Linux基礎】Linux的5種IO模型詳解

引入 為了更好的理解5種IO模型的區別&#xff0c;在介紹IO模型之前&#xff0c;我先介紹幾個概念 1.進程的切換 &#xff08;1&#xff09;定義 為了控制進程的執行&#xff0c;內核必須有能力掛起正在CPU上運行的進程&#xff0c;并恢復以前掛起的某個進程的執行。即從用戶…