多線程編程技術解析及示例:pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock

多線程編程技術解析及示例:pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock

摘要

本文深入解析了多線程編程中 pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock 三個函數的功能、使用場景及注意事項,并通過結合三者的生產者 - 消費者模型 C 語言示例程序,生動展示了它們在實際多線程任務調度中的應用。同時對鎖順序、條件變量使用以及錯誤處理等關鍵要點進行了總結,為開發者在多線程環境下的高效編程與問題解決提供參考。

pthread_mutex_lock 解析

  • 功能 :實現阻塞式加鎖,當鎖被其他線程占用時,調用該函數的線程會掛起等待,直至獲取到鎖。

  • 使用場景

    • 嚴格保護臨界區,防止多個線程同時訪問導致數據不一致,如對共享變量、關鍵數據結構的操作區域進行保護。
    • 確保線程按既定順序訪問共享資源,維持程序的正確執行流程。
  • 注意事項

    • 必須與 pthread_mutex_unlock 成對使用,否則將導致死鎖,線程無法繼續推進,程序陷入僵局。
    • 非遞歸屬性下不可遞歸調用,若需遞歸加鎖,應使用 PTHREAD_MUTEX_RECURSIVE 屬性進行設置。

pthread_mutex_trylock 解析

  • 功能 :以非阻塞方式嘗試加鎖,無論是否成功獲取鎖,都會立即返回相應結果,獲取成功返回 0,失敗則返回 EBUSY 錯誤碼。

  • 使用場景

    • 在嘗試獲取多個鎖時,若獲取其中一個鎖失敗,可及時釋放已持有的其他鎖,避免死鎖發生,提高程序的健壯性。
    • 適用于輕量級任務調度,如需確保同一時刻僅有一個線程執行的單例任務場景。
  • 注意事項

    • 獲取鎖失敗時,必須妥善處理 EBUSY 錯誤,不能直接進入臨界區操作數據,防止數據混亂。
    • 不可與 pthread_mutex_lock 混用,以免造成鎖機制混亂,出現不可預期的錯誤。

pthread_cond_timedwait 解析

  • 功能 :提供帶超時機制的條件變量等待操作,需與互斥鎖配合使用,線程在等待過程中會釋放鎖,在超時或被喚醒時重新嘗試獲取鎖。

  • 使用場景

    • 在生產者 - 消費者模型中,消費者可利用該函數等待任務,若超時未獲取到任務,可執行相應超時處理邏輯。
    • 當線程需在特定時間內響應條件變化時,如實時性要求較高的任務調度場景。
  • 注意事項

    • 超時時間應設置為絕對時間,一般通過 CLOCK_REALTIME 獲取當前時間并加上期望的等待時長來確定。
    • 因可能存在虛假喚醒現象,必須在循環中檢查條件是否真正滿足,若不滿足則繼續等待。
    • 調用前確保已鎖定互斥鎖,返回后線程自動重新加鎖,這是保證數據安全和等待邏輯正確的關鍵。

C 語言示例程序

以下是一個結合 pthread_mutex_lock、pthread_mutex_trylock 和 pthread_cond_timedwait 的生產者 - 消費者模型示例程序,展示了它們在實際場景下的協同工作方式:

#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int task_available = 0;void* producer(void* arg) {while (1) {pthread_mutex_lock(&mutex);task_available = 1;printf("Produced task\n");pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);sleep(1);}return NULL;
}void* consumer(void* arg) {struct timespec ts;while (1) {pthread_mutex_lock(&mutex);clock_gettime(CLOCK_REALTIME, &ts);ts.tv_sec += 2; // 設置 2 秒超時while (!task_available) {if (pthread_cond_timedwait(&cond, &mutex, &ts) == ETIMEDOUT) {printf("Timeout, no task\n");break;}}if (task_available) {printf("Consumed task\n");task_available = 0;}pthread_mutex_unlock(&mutex);// 非阻塞嘗試其他操作if (pthread_mutex_trylock(&mutex) == 0) {printf("Doing non-critical work\n");pthread_mutex_unlock(&mutex);}}return NULL;
}int main() {pthread_t prod, cons;pthread_create(&prod, NULL, producer, NULL);pthread_create(&cons, NULL, consumer, NULL);pthread_join(prod, NULL);pthread_join(cons, NULL);return 0;
}

關鍵總結

鎖順序

在涉及多把鎖的場景中,為防止死鎖,建議按照固定的順序加鎖。例如,若存在鎖 A 和鎖 B,所有線程在獲取鎖時應統一先獲取鎖 A,再獲取鎖 B,從而避免因加鎖順序不一致導致的相互等待僵局。

條件變量

使用條件變量時,由于可能存在虛假喚醒(即線程被喚醒但條件并未真正滿足),必須在循環中反復檢查條件是否滿足,若不滿足則繼續等待,以確保程序邏輯的正確性。

錯誤處理

在調用 pthread_cond_timedwait 時,要檢查其返回值是否為 ETIMEDOUT,以判斷是正常被喚醒還是因超時退出等待;對于 pthread_mutex_trylock,需處理返回的 EBUSY 錯誤碼,避免因獲取鎖失敗而直接進入臨界區引發的問題。

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

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

相關文章

元胞自動機(Cellular Automata, CA)

一、什么是元胞自動機&#xff08;Cellular Automata, CA&#xff09; 元胞自動機&#xff08;CA&#xff09; 是一種基于離散時間、離散空間與規則驅動演化的動力系統&#xff0c;由 馮諾依曼&#xff08;John von Neumann&#xff09; 于1940年代首次提出&#xff0c;用于模…

Flutter面試題

Flutter架構解析 1. Flutter 是什么?它與其他移動開發框架有什么不同? Flutter 是 Google 開發的開源移動應用開發框架,可用于快速構建高性能、高保真的移動應用(iOS 和 Android),也支持 Web、桌面和嵌入式設備。。它與其他移動開發框架(如 React Native、Xamarin、原…

MySQL 如何判斷某個表中是否存在某個字段

在MySQL中&#xff0c;判斷某個表中是否存在某個字段&#xff0c;可以通過查詢系統數據庫 INFORMATION_SCHEMA.COLUMNS 實現。以下是詳細步驟和示例&#xff1a; 方法&#xff1a;使用 INFORMATION_SCHEMA.COLUMNS 通過查詢系統元數據表 COLUMNS&#xff0c;檢查目標字段是否存…

golang 實現基于redis的并行流量控制(計數鎖)

在業務開發中&#xff0c;有時需要對某個操作在整個集群中限制并發度&#xff0c;例如限制大模型對話的并行數。基于redis zset實現計數鎖&#xff0c;做個筆記。 關鍵詞&#xff1a;并行流量控制、計數鎖 package redisutilimport ("context""fmt""…

從線性方程組角度理解公式 s=n?r(3E?A)

從線性方程組角度理解公式 sn?r(3E?A) 這個公式本質上是 ?齊次線性方程組解空間維度 的直接體現。下面通過三個關鍵步驟解釋其在線性方程組中的含義&#xff1a; 1. ?公式對應的線性方程組 考慮矩陣方程&#xff1a; (3E?A)x0 其中&#xff1a; x 是 n 維未知向量3E?…

Docker 在 AI 開發中的實踐:GPU 支持與深度學習環境的容器化

人工智能(AI)和機器學習(ML),特別是深度學習,正以前所未有的速度發展。然而,AI 模型的開發和部署并非易事。開發者常常面臨復雜的依賴管理(如 Python 版本、TensorFlow/PyTorch 版本、CUDA、cuDNN)、異構硬件(CPU 和 GPU)支持以及環境復現困難等痛點。這些挑戰嚴重阻…

解決CSDN等網站訪問不了的問題

原文網址&#xff1a;解決CSDN等網站訪問不了的問題-CSDN博客 簡介 本文介紹解決CSDN等網站訪問不了的方法。 問題描述 CSDN訪問不了了&#xff0c;頁面是空的。 問題解決 方案1&#xff1a;修改DNS 可能是dns的問題&#xff0c;需要重新配置。 國內常用的dns是&#x…

使用tortoisegit連接遠程倉庫進行克隆、拉取、獲取、提交、推送、新建/切換分支、重命名、刪除的一套流程(附帶巨全面的git命令)

1.整備好tortoisegit工具。 2.新建一個文件夾&#xff0c;并進入這個文件夾后鼠標右擊&#xff08;選擇克隆&#xff09;&#xff1a; 3.先去項目中拿到https地址&#xff0c;再填入&#xff1a; 4.新建分支&#xff0c;右擊克隆到本地的項目文件&#xff1a; 5.推送到遠程&am…

ArcGIS Pro 3.4 二次開發 - 地圖創作 1

環境:ArcGIS Pro SDK 3.4 + .NET 8 文章目錄 ArcGIS Pro 3.4 二次開發 - 地圖創作 11 樣式管理1.1 如何通過名稱獲取項目中的樣式1.2 如何創建新樣式1.3 如何向項目添加樣式1.4 如何從項目中移除樣式1.5 如何向樣式添加樣式項1.6 如何從樣式中移除樣式項1.7 如何判斷樣式是否可…

Express 集成Sequelize+Sqlite3 默認開啟WAL 進程間通信 Conf 打包成可執行 exe 文件

代碼&#xff1a;express-exe: 將Express開發的js打包成exe服務丟給客戶端使用 實現目標 Express 集成 Sequelize 操作 Sqlite3 數據庫&#xff1b; 啟動 Sqlite3 時默認開啟 WAL 模式&#xff0c;避免讀寫互鎖&#xff0c;支持并發讀&#xff1b; 利用 Conf 實現主進程與 Ex…

.Net Framework 4/C# 初識 C#

一、C# 專欄 由于博主原先是做的Linux C/C 嵌入式領域&#xff0c;因此對 C# 也較為懵懂&#xff0c;C# 是典型的 OOP 編程&#xff0c;這一點與 C 類似&#xff0c;但是在語法上&#xff0c;C# 移除了對指針的運用以及內存管理&#xff0c;所以既不用考慮指針的復雜運用也不用…

Python趣學篇:Pygame實現粒子煙花綻放效果

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 專欄介紹:《Python星球日記》?? 目錄 一、項目亮點與效果預覽1. 核心特色功能2. 技術學習價值二、技術原理深度解析1. 向量運算:煙花運動的數學基…

NiceGUI 是一個基于 Python 的現代 Web 應用框架

NiceGUI 是一個基于 Python 的現代 Web 應用框架&#xff0c;它允許開發者直接使用 Python 構建交互式 Web 界面&#xff0c;而無需編寫前端代碼。以下是 NiceGUI 的主要功能和特點&#xff1a; 核心功能 1.簡單易用的 UI 組件 提供按鈕、文本框、下拉菜單、滑塊、圖表等常見…

Linux中的mysql邏輯備份與恢復

一、安裝mysql社區服務 二、數據庫的介紹 三、備份類型和備份工具 一、安裝mysql社區服務 這是小編自己寫的&#xff0c;沒有安裝的去看看 Linux換源以及yum安裝nginx和mysql-CSDN博客 二、數據庫的介紹 2.1 數據庫的組成 數據庫是一堆物理文件的集合&#xff0c;主要包括…

鴻蒙UI開發——組件的自適應拉伸

1、概 述 針對常見的開發場景&#xff0c;ArkUI開發框架提供了非常多的自適應布局能力&#xff0c;這些布局可以獨立使用&#xff0c;也可多種布局疊加使用。本文針對ArkUI提供的拉伸能力做簡單討論。 拉伸能力是指容器組件尺寸發生變化時&#xff0c;增加或減小的空間全部分…

K 值選對,準確率翻倍:KNN 算法調參的黃金法則

目錄 一、背景介紹 二、KNN 算法原理 2.1 核心思想 2.2 距離度量方法 2.3 算法流程 2.4算法結構&#xff1a; 三、KNN 算法代碼實現 3.1 基于 Scikit-learn 的簡單實現 3.2 手動實現 KNN&#xff08;自定義代碼&#xff09; 四、K 值選擇與可視化分析 4.1 K 值對分類…

Azure DevOps Server 2022.2 補丁(Patch 5)

微軟Azure DevOps Server的產品組在4月8日發布了2022.2 的第5個補丁。下載路徑為&#xff1a;https://aka.ms/devops2022.2patch5 這個補丁的主要功能是修改了代理(Agent)二進制安裝文件的下載路徑&#xff1b;之前&#xff0c;微軟使用這個CND(域名為vstsagentpackage.azuree…

PHP7+MySQL5.6 查立得輕量級公交查詢系統

# PHP7MySQL5.6 查立得輕量級公交查詢系統 ## 系統簡介 本系統是一個基于PHP7和MySQL5.6的輕量級公交查詢系統(40KB級)&#xff0c;支持線路查詢、站點查詢和換乘查詢功能。系統采用原生PHPMySQL開發&#xff0c;無需第三方框架&#xff0c;適合手機端訪問。 首發版本&#x…

Vue-Cropper:全面掌握圖片裁剪組件

Vue-Cropper 完全學習指南&#xff1a;Vue圖片裁剪組件 &#x1f3af; 什么是 Vue-Cropper&#xff1f; Vue-Cropper 是一個簡單易用的Vue圖片裁剪組件&#xff0c;支持Vue2和Vue3。它提供了豐富的配置選項和回調方法&#xff0c;可以滿足各種圖片裁剪需求。 &#x1f31f; …

[Go] Option選項設計模式 — — 編程方式基礎入門

[Go] Option選項設計模式 — — 編程方式基礎入門 全部代碼地址&#xff0c;歡迎?? Github&#xff1a;https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-option 1 介紹 在 Go 開發中&#xff0c;我們經常遇到需要處理多參數配置的場景。傳統方…