Linux鎖的概念及線程同步

目錄

?

1.常見鎖概念

死鎖

死鎖四個必要條件

避免死鎖

避免死鎖算法

2. Linux線程同步

條件變量

同步概念與競態條件

條件變量函數 初始化

銷毀

等待條件滿足

喚醒等待

簡單案例:

條件變量使用規范


?

1.常見鎖概念

死鎖

死鎖是指在一組進程中的各個進程均占有不會釋放的資源,但因互相申請被其他進程所站用不會釋放的資源而處于的一種永久等待狀態。

死鎖四個必要條件

  • 互斥條件:一個資源每次只能被一個執行流使用
  • 請求與保持條件:一個執行流因請求資源而阻塞時,對已獲得的資源保持不放
  • 不剝奪條件:一個執行流已獲得的資源,在末使用完之前,不能強行剝奪
  • 循環等待條件:若干執行流之間形成一種頭尾相接的循環等待資源的關系

避免死鎖

  • 破壞死鎖的四個必要條件
  • 加鎖順序一致
  • 避免鎖未釋放的場景
  • 資源一次性分配

避免死鎖算法

  • 死鎖檢測算法(了解)

核心思想:通過監控系統資源分配狀態,判斷是否存在死鎖的必要條件(尤其是循環等待),并在檢測到死鎖時觸發恢復機制。

  • 銀行家算法(了解)

核心思想:通過預先判斷資源分配是否會導致系統進入 “不安全狀態”(可能引發死鎖的狀態),來拒絕或允許資源請求,確保系統始終處于 “安全狀態”。

2. Linux線程同步

條件變量

  • 當一個線程互斥地訪問某個變量時,它可能發現在其它線程改變狀態之前,它什么也做不了。
  • 例如一個線程訪問隊列時,發現隊列為空,它只能等待,只到其它線程將一個節點添加到隊列中。這種情況就需要用到條件變量。

同步概念與競態條件

  • 同步:在保證數據安全的前提下,讓線程能夠按照某種特定的順序訪問臨界資源,從而有效避免饑餓問題,叫做同步
  • 競態條件:因為時序問題,而導致程序異常,我們稱之為競態條件。在線程場景下,這種問題也不難理解

條件變量函數 初始化

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict 
attr); 
參數: cond:要初始化的條件變量 attr:NULL 

銷毀

int pthread_cond_destroy(pthread_cond_t *cond) 

等待條件滿足

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); 參數: cond:要在這個條件變量上等待 mutex:互斥量,后面詳細解釋

喚醒等待

int pthread_cond_broadcast(pthread_cond_t *cond); 
向所有等待在該條件變量上的線程發送通知,喚醒所有等待線程。這些線程會在獲取互斥鎖后繼續執行。
int pthread_cond_signal(pthread_cond_t *cond); 
向至少一個等待在該條件變量上的線程發送通知,喚醒至少一個線程(具體喚醒哪個線程由調度器決定)。若有多個線程等待,通常只喚醒一個。

簡單案例:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <pthread.h> pthread_cond_t cond; 
pthread_mutex_t mutex; void *r1( void *arg ) 
{ while ( 1 ){ pthread_cond_wait(&cond, &mutex); printf("活動\n"); } 
} void *r2(void *arg ) 
{ while ( 1 ) {
pthread_cond_signal(&cond); sleep(1); } 
} int main( void ) 
{ pthread_t t1, t2; pthread_cond_init(&cond, NULL); pthread_mutex_init(&mutex, NULL); pthread_create(&t1, NULL, r1, NULL); pthread_create(&t2, NULL, r2, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); 
}  

這段代碼的主要功能就是讓2個線程分別執行:一個一直等待,另一個每隔1秒喚醒它打印。

為什么 pthread_cond_wait 需要互斥量?

  • 條件等待是線程間同步的一種手段,如果只有一個線程,條件不滿足,一直等下去都不會滿足,所以必須要有一個線程通過某些操作,改變共享變量,使原先不滿足的條件變得滿足,并且友好的通知等待在條件變量上的線程。
  • 條件不會無緣無故的突然變得滿足了,必然會牽扯到共享數據的變化。所以一定要用互斥鎖來保護。沒有互斥鎖就無法安全的獲取和修改共享數據。

  • 按照上面的說法,我們設計出如下的代碼:先上鎖,發現條件不滿足,解鎖,然后等待在條件變量上不就行了,如下代碼:
// 錯誤的設計 pthread_mutex_lock(&mutex); while (condition_is_false) { pthread_mutex_unlock(&mutex); //解鎖之后,等待之前,條件可能已經滿足,信號已經發出,但是該信號可能被錯過 pthread_cond_wait(&cond); pthread_mutex_lock(&mutex); } pthread_mutex_unlock(&mutex); 
  • 由于解鎖和等待不是原子操作。調用解鎖之后, 但是在調用pthread_cond_wait 之前,執行被切走了,切到了另一個signal通知線程,他獲取到互斥量,摒棄條件滿足,發送了信號,但是我們之前那個線程并沒有處于等待(還未調用),所以可以理解為等待隊列為空,那么我們回到原先的線程的時候再去調用?pthread_cond_wait 將錯過這個信號,可能會導致線程永遠阻塞在這個 pthread_cond_wait 。所以解鎖和等待必須是一個原子操作。
  • 調用?pthread_cond_wait()?時,線程必須已持有互斥鎖?mutex。函數會原子性地釋放該鎖,并將線程放入?cond?的等待隊列。當其他線程發送信號(如調用?pthread_cond_signal())喚醒該線程時,pthread_cond_wait()?會自動嘗試重新獲取鎖。線程只有在成功獲取鎖后才能從?pthread_cond_wait()?返回,繼續執行后續代碼。

條件變量使用規范

  • 等待條件代碼
pthread_mutex_lock(&mutex); while (條件為假) pthread_cond_wait(cond, mutex); 修改條件 pthread_mutex_unlock(&mutex); 
  • 給條件發送信號代碼
pthread_mutex_lock(&mutex); 設置條件為真 pthread_cond_signal(cond); pthread_mutex_unlock(&mutex); 

?

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

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

相關文章

docker更換國內加速器-更換華為加速器2025-717親測可用docker 拉取鏡像出錯

[rootlocalhost ~]# docker pull nginx Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)報錯原因就是…

Unity VR多人手術模擬恢復2:客戶端移動同步問題分析與解決方案

Unity VR多人手術模擬恢復2&#xff1a;客戶端移動同步問題分析與解決方案 &#x1f3af; 問題背景 在開發基于Unity Mirror網絡架構的VR多人手術模擬系統時&#xff0c;我們遇到了一個復雜的客戶端移動同步問題&#xff1a; 主要操作者&#xff08;第一個客戶端&#xff09;&a…

uni-app開發的頁面跳轉全局加載中

uni-app開發的頁面跳轉全局加載中首先需要下載插件創建加載中頁面組件app.vue頁面中監聽跳轉首先需要下載插件 https://ext.dcloud.net.cn/plugin?id20613 創建加載中頁面組件 <!-- 全局自定義加載中 --> <template><view v-if"visible" class&qu…

XXE漏洞4-XXE無回顯文件讀取-PentesterLab靶場搭建

一.PentesterLab靶場搭建(實驗環境搭建)介紹&#xff1a;PentesterLab 是一個全面的漏洞演示平臺&#xff0c;但是它是收費的&#xff0c;我們這里只使用它的 xxe 演示案例。安裝 PentesterLab 虛擬機:下載好鏡像&#xff1a; 1.打開VMware新建虛擬機&#xff0c;選擇典型就行。…

【機器學習】圖片分類中增強常用方式詳解以及效果展示

圖片增強常用方式詳解 引言 圖片數據的質量和多樣性對模型的訓練效果起著至關重要的作用。然而&#xff0c;實際獲取的圖片數據往往存在數量不足、分布不均衡等問題。圖片增強技術應運而生&#xff0c;它通過對原始圖片進行一系列變換&#xff0c;生成更多具有多樣性的圖片&…

【URL 轉換為PDF】HTML轉換為PDF

1、方法1 pdfkit 安裝依賴 # 安裝 wkhtmltopdf&#xff08;系統級&#xff09; # Ubuntu/Debian sudo apt install wkhtmltopdf# macOS brew install wkhtmltopdf# Windows 下載安裝&#xff1a;https://wkhtmltopdf.org/downloads.html# 安裝 Python 庫 pip install pdfkitimp…

單鏈表的定義、插入和刪除

一、定義一個單鏈表 struct LNode{ //定義單鏈表節點類型ElemType data; //存放節點數據元素struct LNode *next; //指針指向下一個結點 }; //增加一個新節點&#xff1a;在內存中申請一個結點所需空間&#xff0c;并用指針p指向這個結點 struct LNode * p (struc…

Nextjs官方文檔異疑惑

第一個區別&#xff1a;不同的頁面對應的路由器設定&#xff01; 繼續用 app 路由器&#xff08;推薦&#xff0c;Next.js 未來主流&#xff09; 路由規則&#xff1a;app 目錄下&#xff0c;文件夾 page.tsx 對應路由。例如&#xff1a; app/page.tsx → 對應 / 路由&#xf…

突破AI模型訪問的“光標牢籠”:長上下文處理與智能環境隔離實戰

> 當AI模型面對浩瀚文檔卻只能處理零星片段,當關鍵信息散落各處而模型“視而不見”,我們該如何打破這堵無形的墻? 在自然語言處理領域,**輸入長度限制**(常被稱為“光標區域限制”)如同一個無形的牢籠,嚴重制約了大型語言模型(LLM)在真實場景中的應用潛力。無論是分…

AI 智能質檢系統在汽車制造企業的應用?

某知名汽車制造企業在其龐大且復雜的生產流程中&#xff0c;正面臨著棘手的汽車零部件質檢難題。傳統的人工質檢方式&#xff0c;完全依賴人工的肉眼觀察與簡單工具測量。質檢員們長時間處于高強度的工作狀態&#xff0c;精神高度集中&#xff0c;即便如此&#xff0c;由于人工…

設計模式》》門面模式 適配器模式 區別

// 復雜子系統 class CPU {start() { console.log("CPU啟動"); } } class Memory {load() { console.log("內存加載"); } } class HardDrive {read() { console.log("硬盤讀取"); } }// 門面 class ComputerFacade {constructor() {this.cpu ne…

windows內核研究(驅動開發 第一個驅動程序和調試環境搭建)

驅動開發 第一個驅動程序 驅動的開發流程 1.編寫代碼 -> 生成.sys文件 -> 部署 -> 啟動 -> 停止 ->卸載 // 編寫我們的第一個驅動程序 #include<ntddk.h>// 卸載函數 VOID DrvUnload(PDRIVER_OBJECT DriverObject) {DbgPrint("我被卸載了\n"…

ABP VNext + 多級緩存架構:本地 + Redis + CDN

ABP VNext 多級緩存架構&#xff1a;本地 Redis CDN &#x1f4da; 目錄ABP VNext 多級緩存架構&#xff1a;本地 Redis CDN一、引言 &#x1f680;二、環境與依賴 &#x1f6e0;?三、架構概覽 &#x1f310;請求全鏈路示意 &#x1f6e3;?四、本地內存緩存層 &#x1…

RGBA圖片格式轉換為RGB格式(解決convert轉換的失真問題)

使用convert轉換的問題 OpenCV 的 cv2.cvtColor(…, cv2.COLOR_BGRA2GRAY) 會直接忽略 Alpha 通道的含義&#xff0c;將它當作第四個顏色通道來處理。 轉換公式如下&#xff1a; gray 0.114*255 0.587*0 0.299*0 ≈ 29也就是說&#xff0c;即使 Alpha 為 0&#xff08;完全透…

Spring AI之Prompt開發

文章目錄1 提示詞工程1_核心策略2_減少模型“幻覺”的技巧2 提示詞攻擊防范1_提示注入&#xff08;Prompt Injection&#xff09;2_越獄攻擊&#xff08;Jailbreaking&#xff09;3 數據泄露攻擊&#xff08;Data Extraction&#xff09;4 模型欺騙&#xff08;Model Manipulat…

Java面試(基礎篇) - 第二篇!

未看第一篇的&#xff0c;這里可以直達 Java面試(基礎篇) - 第一篇 Integer對象可以用判斷嗎&#xff1f;為什么&#xff1f; 回答 不可以&#xff0c;因為 比較的是對象的實例&#xff08;內存地址&#xff09;&#xff0c;Integer是有一個緩存機制的&#xff0c;它會將-1…

【C# in .NET】11. 探秘泛型:類型參數化革命

探秘泛型:類型參數化革命 泛型是 C# 和.NET框架中一項革命性的特性,它實現了 “編寫一次,多處復用” 的抽象能力,同時保持了靜態類型的安全性和高性能。與 C++ 模板等其他語言的泛型機制不同,.NET 泛型在 CLR(公共語言運行時)層面提供原生支持,這使得它兼具靈活性、安…

菜單權限管理

菜單管理系統的整體架構1.Menu 菜單表2.role 角色表3.role_menu 角色菜 單關聯表&#xff08;多對多 &#xff09;要找role_id為3的角色能用哪個菜單:SELECT *FROM sys_menu a LEFT JOIN sys_role_menu b ON a.menu_id b.menu_id WHERE role_id3拆分開就是4.user 用戶表5.user…

SQL FOREIGN KEY:詳解及其在數據庫設計中的應用

SQL FOREIGN KEY:詳解及其在數據庫設計中的應用 引言 在數據庫設計中,數據完整性是至關重要的。SQL FOREIGN KEY(外鍵)是實現數據完整性的一種有效手段。本文將詳細解釋SQL FOREIGN KEY的概念、用途以及在實際數據庫設計中的應用。 外鍵概述 1. 定義 外鍵(FOREIGN KE…

[yotroy.cool] 記一次 spring boot 項目寶塔面板部署踩坑

個人博客https://www.yotroy.cool/&#xff0c;感謝關注&#xff5e; 圖片資源可能顯示不全&#xff0c;請前往博客查看哦&#xff01;部署了個新項目&#xff0c;給我整抑郁了。。。下面是踩坑過程 寶塔面板 MySql5.7 版本 root 密碼錯誤 這個MySQL5.7 安裝完后就跑不了&#…