進程與線程:09 進程同步與信號量

課程引入:進程同步與信號量

接下來這節課開始,我們再開始講多進程圖像。講多進程圖像的下一個點,前面我們講清楚了多進程圖像要想實現切換,調度是如何做的。同時,多個進程放在內存中,就會存在多進程合作的情況,而這種合作應該是合理有序的,這部分內容就是進程同步——讓多進程之間的合作變得合理有序。那么怎么來實現這種合理有序呢?就要靠信號量。這堂課我們要講清楚為什么會有信號量,以及如何依靠信號量來實現多個進程推進的合理有序,即同步。

現實案例:進程合作與同步的重要性

首先從一個例子看起,在現實社會中,司機和售貨員就如同兩個進程,司機的動作是啟動車、運行、到站停車,售貨員的動作是關門、售票、開門 ,他們各自有一套執行流程。這兩個進程在同一臺車上,為完成車輛的合理有序行駛,必須進行合作。在這里插入圖片描述

  • 不合作的后果:如果二者執行順序沒有約束,比如售票員開門售票時,司機啟動車輛,就會造成嚴重后果。所以,司機啟動車輛不能隨意進行,需要等待一個信號,比如售票員賣完票告知可以走了;同樣,售票員開門也不是隨便進行的,要等車輛到站停車的信號。
  • 合作與同步的體現:司機等待售票員關門的信號再啟動車輛,售票員在車輛到站后得到停車信號才開門,這就體現了進程間的合作。一個進程等待信號,另一個進程在合適的時候發送信號,從而使多個進程按照一定順序向前推進,這就是同步。每個進程有自己的執行程序,但不是每條程序都能隨便執行,有時需要停下來等待信號,當收到信號后再繼續執行,這就是多進程合理有序的合作與同步。

技術案例:生產者 - 消費者模型中的同步問題

接下來以生產者 - 消費者模型為例進一步說明。有一個共享緩沖區,生產者不斷向里放內容,每放完一個 counter 加一;消費者不斷從里取內容,每取出一個 counter 減一 ,這是典型的多進程合作場景。在這里插入圖片描述

  • 同步需求:在這個模型中,也需要合理有序的推進。當生產者發現 counter 等于緩沖區大小 buff size ,即緩沖區滿了,就不能繼續放入,必須等待;同理,當緩沖區為空時,消費者也應該停止。在這里插入圖片描述
    所以,進程同步的關鍵在于分析進程在哪些地方該停、什么時候該走。在生產者 - 消費者模型中,緩沖區滿時生產者停,消費者消費后產生空閑緩沖區,就給生產者發信號讓其繼續;緩沖區空時消費者停,生產者生產后給消費者發信號。在這里插入圖片描述

  • 信號的局限性:僅依靠信號存在問題。例如,當緩沖區滿時,生產者 p1 嘗試放入會因 counter 等于 buff sizesleep ,之后另一個生產者 p2 進來,同樣會 sleep 。此時若消費者執行一次循環,取出一個內容, counter 變為 buff size - 1 ,消費者判斷緩沖區未滿,認為無人等待緩沖區,不會再發信號喚醒 p2 ,導致 p2 永遠無法喚醒。這說明單純依靠 counter 進行語義判斷不足,不僅需要知道緩沖區中空閑個數,還需知道有多少進程在睡眠等待。

信號量的引入與原理在這里插入圖片描述

為解決上述問題,引入信號量。信號量是一個整數,它能記錄更多信息。例如信號量等于 -2 ,表示有兩個進程在等待 。當消費者執行時,發現信號量為 -2 ,就會喚醒阻塞隊列頭部的進程(如 p1 ),同時信號量變為 -1 ;再次執行,喚醒 p2 ,信號量變為 0
在這里插入圖片描述

  • 信號量的語義:信號量為負數時,表示有進程阻塞,其絕對值代表等待進程的數量;為 0 時,表示沒有進程等待,但也沒有可用資源;為正數時,表示有可用資源,數值代表資源數量 。如消費者執行使信號量變為 1 ,表示還有一個空閑緩沖區,此時若有新的生產者 p3 來,無需睡眠可直接執行,執行后信號量變為 0 ;再有生產者來,信號量變為 -1 ,該生產者需阻塞等待。
  • 基于信號量的進程決策:進程根據信號量的值決定是否等待或喚醒其他進程。生產者申請使用資源(如空閑緩沖區)時,若信號量為負或零,說明資源不足或已用完,需等待;消費者釋放資源(產生空閑緩沖區)時,若信號量為負,說明有進程在等待,需喚醒一個等待進程。

信號量與資源等待的關系

我們可以根據這個習題來回答,對于一種數量為八的資源,思考進程等待的原因。進程等待肯定是因為申請資源時沒有可用資源了。在進程同步中,競爭合作體現為走走停停,而“停滯”是其中的核心,所以明確進程何時等待至關重要。當一個進程訪問資源卻發現沒有資源時,就會進入等待狀態。在這里插入圖片描述

這種資源對應的信號量初值應該設為八,這表示初始狀態下可以使用八個該資源。當信號量的值變為零時,意味著沒有資源剩余,若值再變為負數,進程就需要等待。當信號量的值為二時,說明還有兩個資源可供使用,此時沒有進程在等待該資源;而當信號量的值為 -2 時,則表示有兩個進程正在等待該資源 。

通過信號量的值,我們能夠判斷系統中有多少進程在等待資源,以及還有多少資源可供使用。基于這樣的判斷,我們可以控制進程的執行與暫停,從而實現進程同步,其核心就在于依據信號量的值來判斷進程何時該“走”、何時該“停”。

信號量的核心概念與操作

  1. 信號量的定義與作用
    進程之間的同步是多個進程走走停停的合理有序推進,判斷何時停要看信號量的值。當信號量為負值或 0 時,進程申請信號量會變成負值,此時進程等待;其他進程根據信號量的值,若為負,在釋放信號量時進行喚醒操作;若為正,直接累加,無需發信號。

  2. 信號量的實現方式
    在編程實現中,判斷進程是否需要等待資源是通過調用函數來完成的,這就涉及到信號量的具體實現。信號量的核心是一個整數,它記錄著資源的相關信息。為了方便用戶操作,我們通過定義 PV 操作這兩個接口函數來實現對信號量的控制。在這里插入圖片描述

    • P 操作:當進程想要申請資源,判斷自己是否應該暫停時,就調用 P 操作。以 P(sem) 為例,執行該操作時,首先將信號量 sem 的值減 1。這是因為進程申請資源,相當于資源數量減少。如果減 1 后信號量的值小于 0,說明在本次申請之前,資源要么已經沒有剩余(值為 0),要么已經處于供不應求的狀態(值為負),當前進程無法獲得資源,此時進程就會進入睡眠狀態,并被放入與該信號量相關聯的阻塞隊列中。例如,生產者進程每次使用空閑緩沖區時,就需要對空閑緩沖區對應的信號量執行 P 操作,以此判斷是否有空閑緩沖區可供使用,如果沒有則進入等待。
    • V 操作:有進程等待,就需要有喚醒操作,這就是 V 操作的作用。當進程釋放資源時,會調用 V 操作。執行 V 操作時,將信號量的值加 1 ,這表示資源數量增加。如果加 1 后信號量的值仍然小于等于 0,說明在釋放資源之前,有進程在等待該資源(信號量為負表示等待進程數,為 0 表示剛有進程等到資源),此時就需要調用 wake up 函數,從阻塞隊列中喚醒一個進程;如果加 1 后信號量的值大于 0 ,則表示沒有進程在睡眠等待,無需進行喚醒操作。比如消費者進程產生空閑緩沖區后,就會對相應的信號量執行 V 操作。
    • 系統調用:由于信號量操作涉及到進程睡眠等在內核態完成的操作,所以 PV 操作需要做成系統調用,這樣上層應用程序就能通過調用系統調用來使用信號量。其中,P 操作源于荷蘭語“test”,表示測試是否需要阻塞;V 操作源于荷蘭語“increment”,表示增加資源數量,進而實現喚醒等待進程的功能 。

信號量解決生產者 - 消費者問題

利用信號量及其 PV 操作,可以有效解決生產者 - 消費者問題,實現進程間的同步與合作。在解決該問題時,關鍵在于分析生產者和消費者何時會暫停,并據此定義相應的信號量。在這里插入圖片描述

  1. 分析生產者與消費者的等待條件
    • 生產者:當緩沖區滿時會停,所以定義一個信號量 empty 表示空閑緩沖區個數,初值為 buff_size 。生產者每次操作前先執行 P(empty) ,測試 empty 是否為 0 ,即緩沖區是否滿,若滿則等待。當消費者釋放空閑緩沖區時,執行 V(empty) 增加 empty 的值 。
    • 消費者:當緩沖區沒有內容時會停,定義一個信號量 full 表示已生產內容的個數,初值為 0 。消費者每次操作前先執行 P(full) ,測試 full 是否為 0 ,即是否有內容,若無則等待。當生產者生產內容后,執行 V(full) 增加 full 的值 。
  2. 互斥信號量實現共享資源互斥訪問
    共享緩沖區(可視為文件)的操作需要互斥,即同一時刻只能有一個進程訪問。定義一個互斥信號量 mutex ,初值為 1 。生產者和消費者在訪問共享緩沖區前,先執行 P(mutex) ,若 mutex 等于 1 ,則變為 0 ,進程進入;訪問結束后執行 V(mutex) 釋放資源,使其他進程可以進入 。

通過上述信號量的設置以及 PV 操作的合理運用,依據信號量數值所代表的語義,準確判斷進程是否需要睡眠或喚醒其他進程,從而實現了生產者和消費者之間執行過程的合理有序,最終解決了進程同步問題,實現了二者的合作 。

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

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

相關文章

【愚公系列】《Manus極簡入門》036-物聯網系統架構師:“萬物互聯師”

🌟【技術大咖愚公搬代碼:全棧專家的成長之路,你關注的寶藏博主在這里!】🌟 📣開發者圈持續輸出高質量干貨的"愚公精神"踐行者——全網百萬開發者都在追更的頂級技術博主! &#x1f…

MySQL 8.0 OCP 英文題庫解析(四)

Oracle 為慶祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免費考取原價245美元的MySQL OCP 認證。 從今天開始,將英文題庫免費公布出來,并進行解析,幫助大家在一個月之內輕松通過OCP認證。 本期公布試題26~30 試題26:…

什么是原碼和補碼

補碼的本質確實是模運算(Modular Arithmetic),這是理解補碼為何能統一加減法的核心數學原理。下面用最通俗的語言和例子解釋清楚: —### 1. 先理解什么是“模運算”- 模運算就是“周期性計數”,比如鐘表: -…

筆記項目 day02

一、用戶登錄接口 請求參數: 用loginDTO來封裝請求參數,要加上RequestBody注解 響應參數: 由于data里內容較多,考慮將其封裝到一個LoginUser的實體中,用戶登陸后,需要生成jwtToken并返回給前端。 登錄功…

2025年土木建筑與水利工程國際會議(ICCHE 2025)

2025 International Conference on Civil and Hydraulic Engineering (ICCHE 2025) (一)會議信息 會議簡稱:ICCHE 2025 大會地點:中國銀川 投稿郵箱:icchesub-paper.com 收錄檢索:提交Ei Compendex,CPCI,C…

運行Spark程序-在shell中運行1

(一)分布式計算要處理的問題 【老師提問:分布式計算要面臨什么問題?】 【老師總結】 分布式計算需要做到: 1.分區控制。把大的數據拆成一小份一小份的(分區,分片)讓多臺設備同時計算…

一文理清人工智能,機器學習,深度學習的概念

目錄 一、人工智能的起源與核心范疇(1950-1980) 1.1 智能機器的最初構想 1.2 核心范疇的初步分化 二、機器學習的興起與技術分化(1980-2010) 2.1 統計學習的黃金時代 2.2 神經網絡的復興與子集定位 2.3 技術生態的形成與AI…

《Effective Python》第1章 Pythonic 思維總結——編寫優雅、高效的 Python 代碼

《Effective Python》第1章 Pythonic 思維總結——編寫優雅、高效的 Python 代碼 在編程的世界里,每個語言都有其獨特的風格和最佳實踐。對于 Python 而言,“Pythonic”已經成為描述遵循 Python 特定風格的代碼的代名詞。這種風格不僅讓代碼更易讀、更簡…

MySQL 事務(二)

文章目錄 事務隔離性理論理解隔離性隔離級別 事務隔離級別的設置和查看事務隔離級別讀未提交讀提交(不可重復讀) 事務隔離性理論 理解隔離性 MySQL服務可能會同時被多個客戶端進程(線程)訪問,訪問的方式以事務方式進行一個事務可能由多條SQL…

代碼倉提交分支規范

以下是我部門開發時用的分支規范,參考于Linux社區 Tips 分支命名通常遵循一些最佳實踐和規則,以便使分支的用途和內容清晰易懂,就在寫一個文檔的主題一樣。 功能分支 (Feature Branches) 用于開發新功能。 命名格式:feature/功能名…

Google Earth Engine(GEE) 代碼詳解:批量計算_年 NDVI 并導出(附 Landsat 8 數據處理全流程)

一、代碼整體目標 基于 Landsat 8 衛星數據,批量計算 2013-2020 年研究區的 NDVI(歸一化植被指數),實現去云處理、數據合成、可視化及批量導出為 GeoTIFF 格式,適用于植被動態監測、生態環境評估等場景。 二、代碼分步解析(含核心原理與易錯點) 1. 加載并顯示研究區邊…

Maven 處理依賴沖突

Maven處理依賴沖突 什么是依賴沖突?如何解決?Maven自動處理依賴沖突的規則路徑優先原則第一聲明優先原則注意 子模塊覆蓋父模塊父模塊聲明dependency子模塊覆蓋dependency父模塊聲明dependencyManagement 子模塊覆蓋dependency父模塊聲明dependencyManag…

docker 安裝 sqlserver2022 和注意點

一、前言 1、可以直接參考微軟官方文檔 快速入門:使用 Docker 運行 SQL Server Linux 容器映像,這里主要是說一些注意點和坑 二、安裝 1、拉取鏡像 docker pull mcr.microsoft.com/mssql/server:2022-latest2、創建掛載目錄,這里只是比官方…

Dagster Pipes系列-1:調用外部Python腳本

本文是"Dagster Pipes教程"的第一部分,介紹如何通過Dagster資產調用外部Python腳本并集成到數據管道中。首先,創建Dagster資產subprocess_asset,利用PipesSubprocessClient資源執行外部腳本external_code.py,實現跨進程…

【SQL系列】多表關聯更新

💝💝💝歡迎來到我的博客,很高興能夠在這里和您見面!希望您在這里可以感受到一份輕松愉快的氛圍,不僅可以獲得有趣的內容和知識,也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

C++進階學習:STL常用容器--map/multimap容器

1. map 容器基本概念 map 中所有元素都是 pair pair 中第一個元素為 key (鍵值) 起到索引運用 第二個元素為 value(實值) 所有元素都會根據元素的鍵值自動排序 本質: map/multimap 屬于關聯式容器 底層結構是用二…

let,const,var關鍵字的區別

let,const,var關鍵字 let,const,var都存在變量提升 它們都存在變量提升但是稍微有點不同 var變量聲明會被提升到作用域的頂部,并且會被初始化為 undefinedlet 和 const:變量聲明也會被提升到作用域的頂部,但不會被初…

Nuitka 已經不再安全? Nuitka/Cython 打包應用逆向工具 -- pymodhook

pymodhook是一個記錄任意對Python模塊的調用的庫,用于Python逆向分析。 pymodhook庫類似于Android的xposed框架,但不僅能記錄函數的調用參數和返回值,還能記錄模塊的類的任意方法調用,以及任意派生對象的訪問,基于pyob…

path環境變量滿了如何處理,分割 PATH 到 Path1 和 Path2

要正確設置 Path1 的值,你需要將現有的 PATH 環境變量 中的部分路徑復制到 Path1 和 Path2 中。以下是詳細步驟: 步驟 1:獲取當前 PATH 的值 打開環境變量窗口: 按 Win R,輸入 sysdm.cpl,點擊 確定。在 系…

SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理標準)-(一)

1 目的 物料(例如晶圓)加工在設備中的自動化管理與控制是實現工廠自動化的關鍵要素。本標準針對半導體制造環境中與設備內部物料處理相關的通信需求進行了規范。本標準規定了在加工單元接收到的指定材料所應適用的加工方法(例如Etch腔室需要Run哪支Recipe)。它闡述了物料加工的…