進程互斥的軟件實現方法

單標志法

算法思想:兩個進程在訪問完臨界區后會把使用臨界區的權限轉交給另一個進程。也就是說每個進程進入臨界區的權限只能被另一個進程賦予

int turn = 0; //turn 表示當前允許進入臨界區的進程號P0 進程:
while (turn != 0);  ① //進入區
critical section;   ② //臨界區
turn = 1;           ③ //退出區
remainder section;  ④ //剩余區P1進程:
while (turn != 1);  ⑤ //進入區
critical section;   ⑥ //臨界區
turn = 0;           ⑦ //退出區
remainder section;  ⑧ //剩余區

turn 的初值為 0,即剛開始只允許 0 號進程進入臨界區。 若 P1 先上處理機運行,則會一直卡在 ⑤。直到 P1 的時間片用完,發生調度,切換 P0 上處理機運行。代碼 ① 不會卡住 P0,P0 可以正常訪問臨界區,在 P0 訪問臨界區期間即時切換回 P1,P1 依然會卡在 ⑤。只有 P0 在退出區將 turn 改為 1 后,P1 才能進入臨界區。

因此,該算法可以實現“同一時刻最多只允許一個進程訪問臨界區”

存在的問題:

場景舉例說明

讓我們一步步模擬:

  1. 初始狀態:

    • turn = 0 → 表示現在輪到 P0 可以進入臨界區

    • P1 想進入臨界區,于是執行 while (turn != 1),發現不滿足,只能等待

    • P0 其實此時沒什么事,不想進臨界區,也不運行相關代碼

  2. 結果:

    • P1 一直卡在 while (turn != 1),根本進不去臨界區;

    • turn 又不會自動改變(P0 不進入臨界區,就不會執行 turn = 1);

    • P1 陷入“饑餓”狀態:它想進入,但“鑰匙”還在 P0 手上;

    • 同時,P1 在那兒空等浪費 CPU(忙等待)→ 資源浪費

雙標志先檢查法

算法思想:
  • 每個進程設置一個布爾型變量 flag[i] 來表示自己是否想進入臨界區

  • 進程在進入臨界區之前,先檢查另一個進程的 flag 值,看對方是否也想進入。

  • 如果對方也想進入,就進入忙等待

  • 如果對方沒有想進入,則自己設置自己的 flagtrue,然后進入臨界區。

設置一個布爾型數組 flag[],數組中各個元素用來標記各進程想進入臨界區的意愿,比如“flag[0] = true”意味著 0 號進程 P0 現在想要進入臨界區。每個進程在進入臨界區之前先檢查當前有沒有別的進程想進入臨界區,如果沒有,則把自身對應的標志 flag[i] 設為 true,之后開始訪問臨界區。

bool flag[2]; //表示進入臨界區意愿的數組
flag[0] = false;
flag[1] = false; //剛開始設置為兩個進程都不想進入臨界區P0 進程:
while (flag[1]); ①
flag[0] = true;  ②    //進入區
critical section; ③
flag[0] = false; ④
remainder section;P1 進程:
while (flag[0]); ⑤ //如果此時 P0 想進入臨界區,P1 就一直循環等待
flag[1] = true;  ⑥ //標記為 P1 進程想要進入臨界區  (進入區)
critical section; ⑦ //訪問臨界區
flag[1] = false; ⑧ //訪問完臨界區,修改標記為 P1 不想使用臨界區
remainder section;
存在的問題

?1. 不能保證互斥(互斥性失效)(按①⑤②⑥這樣的順序執行就會導致這樣)

場景設定:

兩個進程 P0 和 P1 幾乎同時想進入臨界區

步驟拆解:

  1. 系統調度讓 P0 和 P1 幾乎同時執行到 while(flag[對方])

    • P0 執行 while(flag[1]),發現 flag[1] == false(因為 P1 還沒設置)

    • P1 執行 while(flag[0]),也發現 flag[0] == false(因為 P0 還沒設置)

  2. 因此:

    • P0 認為 P1 沒想進,就放心地執行 flag[0] = true

    • P1 也認為 P0 沒想進,就也執行 flag[1] = true

  3. 結果:P0 和 P1 都設置了自己的 flagtrue,都進入了臨界區!

  4. ? 互斥性就失敗了:兩個進程同時訪問共享資源

若按照①⑤②⑥③⑦...的順序執行,P0 和 P1 將會同時訪問臨界區。 因此,雙標志先檢查法的主要問題是:違反“忙則等待”原則。 原因在于,進入區的“檢查”和“上鎖”兩個處理不是一氣呵成的。“檢查”后,“上鎖”前可能發生進程切換。

雙標志后檢查法

算法思想:

先聲明意圖(上鎖)再檢查對方是否也要進。

這樣做的原因是:
在先檢查后上鎖(比如前面的雙標志先檢查法)中,兩個進程都可能誤以為對方沒想進,然后都進入臨界區,違反了互斥原則。

所以這里改進成:

  1. 每個進程先把自己的 flag[i] 設置為 true,表示“我要進臨界區”;

  2. 然后檢查對方的 flag[j]

  3. 如果對方也想進,就等待;

  4. 如果對方不想進,就進入臨界區。

bool flag[2]; //表示進入臨界區意愿的數組
flag[0] = false;
flag[1] = false; //剛開始設置為兩個進程都不想進入臨界區P0 進程:
flag[0] = true;  ①
while (flag[1]); ②
critical section; ③
flag[0] = false; ④
remainder section;P1 進程:
flag[1] = true;  ⑤ //標記為 P1 進程想要進入臨界區
while (flag[0]); ⑥ //如果 P0 也想進入臨界區,則 P1 循環等待
critical section; ⑦ //訪問臨界區
flag[1] = false; ⑧ //訪問完臨界區,修改標記為 P1 不想使用臨界區
remainder section;

若按照①⑤②⑥...的順序執行,P0 和 P1 將都無法進入臨界區 因此,雙標志后檢查法雖然解決了“忙則等待”的問題,但是又違背了“空閑讓進”和“有限等待”原則,會因各進程都長期無法訪問臨界資源而產生“饑餓”現象。

如果兩個進程同時幾乎執行到①⑤這一步

  • P0 執行 flag[0] = true;

  • P1 執行 flag[1] = true;

  • 然后:

    • P0 進入 while (flag[1]);,發現 flag[1] == true → 開始等待

    • P1 進入 while (flag[0]);,發現 flag[0] == true → 也開始等待

于是,兩個進程都在等待對方放棄進入臨界區,但又誰都不愿意主動放棄 → 形成了“互相謙讓”卻“都進不去”的尷尬狀態

這就是所謂的:

? 饑餓現象(Starvation)和活鎖(Live Lock)

  • 饑餓(Starvation):進程長期得不到所需資源(臨界區)

  • 活鎖(Live Lock):進程雖然一直在“活動”地等待(沒有卡死),但實際上也永遠得不到執行的機會

Peterson 算法代碼

bool flag[2] = {false, false}; // 表示兩個進程是否想進
int turn = 0;                  // 表示讓誰先進入(初始給 P0)// P0 進程:
flag[0] = true;      // ① 表示想進入臨界區
turn = 1;            // ② 表示讓對方先試
while (flag[1] && turn == 1);  // ③ 如果 P1 想進 且 turn 讓 P1 先 → 等
critical section;   // ④ 臨界區
flag[0] = false;     // ⑤ 退出臨界區,表示不想進了// P1 進程:
flag[1] = true;
turn = 0;
while (flag[0] && turn == 0);
critical section;
flag[1] = false;

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

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

相關文章

力扣150題-- 匯總區間和合并區間

Day 27 題目描述 思路 做法: 特殊處理空數組和數組只有一個元素的情況設置beg,end標記范圍的起始和結束,x用來比較元素是否有序(初始end和beg都指向nums[0[,x為nums[0]1)遍歷數組如果當前元素等于x,說明…

【c++深入系列】:萬字string詳解(附有sso優化版本的string模擬實現源碼)

🔥 本文專欄:c 🌸作者主頁:努力努力再努力wz 💪 今日博客勵志語錄: 當你想放棄時,想想為什么當初堅持走到了這里 ★★★ 本文前置知識: 類和對象(上) 類和對…

Spark-Streaming簡介和核心編程

Spark-Streaming簡介 概述:用于流式數據處理,支持Kafka、Flume等多種數據輸入源,可使用Spark原語運算,結果能保存到HDFS、數據庫等。它以DStream(離散化流)為抽象表示,是RDD在實時場景的封裝&am…

verilog中的約束信息

1、保持約束 keep:當編譯器在對FPGA設計進行映射時,一些線網將會被吸收到邏輯塊中。 (* KEEP "{TRUE | FALSE}" *) keep_hierarchy:vivado默認會把設計變成一級一級模塊化的調用轉換為一個沒有子模塊的超大模塊。這個約束會保留部分層級關系…

Missashe考研日記-day24

Missashe考研日記-day24 1 專業課408 學習時間:2h30min學習內容: 今天把剩下的兩個經典同步問題和管程部分的課看了,然后做課后習題。這部分的重點在PV大題,很多很經典,不過第一輪不打算做大題,把選擇題做…

力扣每日打卡17 49. 字母異位詞分組 (中等)

力扣 49. 字母異位詞分組 中等 前言一、題目內容二、解題方法1. 哈希函數2.官方題解2.1 前言2.2 方法一:排序2.2 方法二:計數 前言 這是刷算法題的第十七天,用到的語言是JS 題目:力扣 49. 字母異位詞分組 (中等) 一、題目內容 給…

C#抽象類和虛方法的作用是什么?

抽象類 (abstract class): 不能直接實例化,只能被繼承。 用來定義一套基礎框架和規范,強制子類必須實現某些方法(抽象方法)。 可用來封裝一些共通的邏輯,減少代碼重復。 虛方法 (virtual): …

PowerBi中ALLEXCEPT怎么使用?

在 Power BI 的 DAX 中,ALLEXCEPT() 是一個非常重要的函數,用來實現**“在保留部分篩選條件的前提下,移除其他所有篩選器”**,它常用于 同比、占比、累計匯總 等分析中。 ? 一、ALLEXCEPT 是什么意思? 函數全稱&…

IQ信號和實信號的關系與轉換的matlab實現

IQ信號 IQ信號通常是指兩路正交的信號(I路和Q路),在實際信號采樣中,通常會進行IQ采樣,將實信號轉換為復基帶信號進行存儲。 IQ信號轉實信號 IQ信號轉為實信號,其實就是將IQ兩路正交信號通過上變頻合并為一個實數的帶通信號,這通常在通信系統中用于將基帶信號調制到載…

【鋰電池剩余壽命預測】LSTM長短期記憶神經網絡鋰電池剩余壽命預測(Matlab源碼)

目錄 效果一覽程序獲取程序內容代碼分享研究內容基于LSTM長短期記憶神經網絡的鋰電池剩余壽命預測摘要關鍵詞1. 引言1.1 研究背景1.2 研究現狀與問題1.3 研究目的與意義2. 文獻綜述2.1 鋰電池剩余壽命預測方法概述2.2 傳統預測方法的優勢與不足2.3 LSTM在鋰電池壽命預測中的應用…

具身智能的理論基礎

引言 在人工智能與認知科學快速發展的背景下,“具身智能”(Embodied Intelligence)這一概念日益受到重視。具身智能是指智能體的認知能力不僅源于其大腦(或中央處理單元),更根植于其身體的結構、感官與其所…

【數據結構】勵志大廠版·初級(二刷復習)雙鏈表

前引:今天學習的雙鏈表屬于鏈表結構中最復雜的一種(帶頭雙向循環鏈表),按照安排,我們會先進行復習,如何實現雙鏈表,如基本的頭插、頭刪、尾刪、尾插,掌握每個細節,隨后進…

CSS `display` 屬性詳解(完整版)

CSS display 屬性詳解(完整版) 1. 屬性值及特性詳解 display 屬性控制元素的布局類型和生成的框類型,以下是 所有有效值 及其特性: 1.1 基礎類型 值描述布局行為是否生成塊級框典型用途block元素獨占一行,寬度自動撐…

【數據結構 · 初階】- 堆的實現

目錄 一.初始化 二.插入 三.刪除(堆頂、根) 四.整體代碼 Heap.h Test.c Heap.c 我們使用順序結構實現完全二叉樹,也就是堆的實現 以前學的數據結構只是單純的存儲數據。堆除了存儲數據,還有其他的價值——排序。是一個功能…

qt.tlsbackend.ossl: Failed to load libssl/libcrypto.

我的環境是windows,QT6.3.2(msvc2019_64/mingw_64) 出錯原因 QT沒有正確加載OpenSSL。 解決過程 1、確保安裝的有openssl。 文章結尾有個注意,是其他方式安裝過openssl,環境變量有,但是QT找不到的問題。…

【Linux】用戶權限

shell命令 1. Linux本質上是一個操作系統,但是一般的用戶不能直接使用它,而是需要通過外殼程序shell,來與Linux內核進行溝通。 2. shell的簡單定義:命令行解釋器。主要包含以下作用: 將使用者的命令翻譯給核心處理。將…

賽靈思 XC7K325T-2FFG900I FPGA Xilinx Kintex?7

XC7K325T-2FFG900I 是 Xilinx Kintex?7 系列中一款工業級 (I) 高性能 FPGA,基于 28 nm HKMG HPL 工藝制程,核心電壓標稱 1.0 V,I/O 電壓可在 0.97 V–1.03 V 之間靈活配置,并可在 –40 C 至 100 C 溫度范圍內穩定運行。該器件提供…

【題解-Acwing】847. 圖中點的層次

題目:847. 圖中點的層次 題目描述 給定一個 n 個點 m 條邊的有向圖,圖中可能存在重邊和自環。 所有邊的長度都是 1,點的編號為 1~n。 請你求出 1 號點到 n 號點的最短距離,如果從 1 號點無法走到 n 號點,輸出 ?1 。 輸入 第一行包含兩個整數 n 和 m。 接下來 m 行…

css圖片設為灰色

使用filter方式將圖片設置為灰色 普通圖片使用&#xff1a;filter: saturate(0); 純白圖片使用&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"width…

【Luogu】動態規劃一

P5414 [YNOI2019] 排序 - 洛谷 思路&#xff1a; 可以想到對于任意一個需要換位置的數字&#xff0c;我們不可能換兩次及以上&#xff0c;那么這題就可以轉化為求一個最大和的最長不遞減子序列&#xff0c;最后的答案就是眾和減去這個最大和 代碼&#xff1a; #include <…