鎖(Mutex)、信號量(Semaphore)與條件量(Condition Variable)


一、同步機制的核心意義

在多線程/多進程編程中,當多個執行流共享資源(如變量、內存、文件)時,可能因操作順序不確定導致數據競爭(Data Race)。同步機制的作用是:

  1. 保證原子性:確保關鍵代碼段(Critical Section)的獨占訪問。
  2. 協調執行順序:控制線程/進程的執行順序(如生產者-消費者模型)。

二、鎖(Mutex)

1. 基本概念
  • 互斥鎖(Mutex):最簡單的同步工具,確保同一時間只有一個線程訪問共享資源。
  • 特性:鎖被占用時,其他嘗試獲取鎖的線程會被阻塞,直到鎖被釋放。
2. 使用步驟
  1. 初始化鎖
  2. 進入臨界區前加鎖
  3. 退出臨界區后解鎖
  4. 銷毀鎖
3. 示例:多線程計數器
#include <pthread.h>
#include <stdio.h>int counter = 0;
pthread_mutex_t lock; // 定義互斥鎖void* increment(void* arg) {for (int i = 0; i < 100000; i++) {pthread_mutex_lock(&lock); // 加鎖counter++;pthread_mutex_unlock(&lock); // 解鎖}return NULL;
}int main() {pthread_t t1, t2;pthread_mutex_init(&lock, NULL); // 初始化鎖pthread_create(&t1, NULL, increment, NULL);pthread_create(&t2, NULL, increment, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);printf("Final counter: %d\n", counter); // 正確輸出 200000pthread_mutex_destroy(&lock); // 銷毀鎖return 0;
}

關鍵點:若不加鎖,counter++(非原子操作)會導致結果錯誤。


三、信號量(Semaphore)

1. 基本概念
  • 信號量:一種更通用的同步工具,可以控制多個線程對資源的訪問。
  • 類型
    • 二進制信號量:取值0或1,功能類似鎖。
    • 計數信號量:允許指定數量的線程同時訪問資源。
2. 使用場景
  • 限制資源并發訪問數(如數據庫連接池)。
  • 生產者-消費者模型(緩沖區大小控制)。
3. 示例:生產者-消費者模型
#include <semaphore.h>
#include <pthread.h>
#define BUFFER_SIZE 5int buffer[BUFFER_SIZE];
sem_t empty, full; // 定義信號量
int in = 0, out = 0;void* producer(void* arg) {for (int i = 0; i < 10; i++) {sem_wait(&empty); // 等待空位(empty-1)buffer[in] = i;in = (in + 1) % BUFFER_SIZE;sem_post(&full); // 通知有數據(full+1)}return NULL;
}void* consumer(void* arg) {for (int i = 0; i < 10; i++) {sem_wait(&full); // 等待數據(full-1)printf("Consumed: %d\n", buffer[out]);out = (out + 1) % BUFFER_SIZE;sem_post(&empty); // 釋放空位(empty+1)}return NULL;
}int main() {sem_init(&empty, 0, BUFFER_SIZE); // 初始空位數量=5sem_init(&full, 0, 0);            // 初始數據數量=0pthread_t p, c;pthread_create(&p, NULL, producer, NULL);pthread_create(&c, NULL, consumer, NULL);pthread_join(p, NULL);pthread_join(c, NULL);sem_destroy(&empty);sem_destroy(&full);return 0;
}

關鍵點:通過 emptyfull 信號量協調生產者和消費者的執行順序。


四、條件變量(Condition Variable)

1. 基本概念
  • 條件變量:允許線程在某個條件不滿足時主動阻塞,并在條件滿足時被喚醒。
  • 必須與互斥鎖配合使用:確保檢查和修改條件的原子性。
2. 使用場景
  • 等待特定條件(如任務隊列非空)。
  • 避免忙等待(Busy Waiting),節省CPU資源。
3. 示例:任務隊列調度
#include <pthread.h>
#include <stdbool.h>pthread_mutex_t lock;
pthread_cond_t cond;   // 條件變量
bool task_available = false;void* worker(void* arg) {pthread_mutex_lock(&lock);while (!task_available) {pthread_cond_wait(&cond, &lock); // 阻塞并釋放鎖,被喚醒后自動重新加鎖}printf("Processing task...\n");task_available = false;pthread_mutex_unlock(&lock);return NULL;
}void* scheduler(void* arg) {pthread_mutex_lock(&lock);task_available = true;pthread_cond_signal(&cond); // 喚醒等待的線程pthread_mutex_unlock(&lock);return NULL;
}int main() {pthread_t t_worker, t_scheduler;pthread_mutex_init(&lock, NULL);pthread_cond_init(&cond, NULL);pthread_create(&t_worker, NULL, worker, NULL);sleep(1); // 確保worker先進入等待pthread_create(&t_scheduler, NULL, scheduler, NULL);pthread_join(t_worker, NULL);pthread_join(t_scheduler, NULL);pthread_mutex_destroy(&lock);pthread_cond_destroy(&cond);return 0;
}

關鍵點

  • pthread_cond_wait原子性地釋放鎖并阻塞線程,被喚醒后重新獲取鎖。
  • 必須使用 while 檢查條件(避免虛假喚醒)。

五、三者的對比與選擇

機制用途特點
保護臨界區,確保獨占訪問簡單、輕量,僅支持互斥
信號量控制資源訪問數量或協調執行順序靈活,支持計數和復雜同步邏輯
條件變量等待特定條件成立需與鎖配合,避免忙等待

選擇原則

  • 簡單互斥 → 鎖。
  • 控制資源數量 → 信號量。
  • 等待條件成立 → 條件變量。

六、深入:常見問題與陷阱

  1. 死鎖

    • 場景:多個鎖未按順序獲取。
    • 解決:統一加鎖順序,或使用超時機制(如 pthread_mutex_trylock)。
  2. 優先級反轉

    • 場景:低優先級線程持有高優先級線程需要的鎖。
    • 解決:優先級繼承(如 pthread_mutexattr_setprotocol)。
  3. 虛假喚醒

    • 場景:pthread_cond_wait 可能無故返回。
    • 解決:始終在 while 循環中檢查條件。

通過合理使用鎖、信號量和條件變量,可以構建高效且安全的并發程序。實際開發中需嚴格測試同步邏輯。

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

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

相關文章

前端基礎之《Vue(6)—組件基礎(2)》

接上一篇。 七、v-model深入學習 <html> <head><title>組件基礎-4</title><style>.score {display: inline-block;}.score>span {display: inline-block;width: 25px;height: 25px;background: url(./assets/star.png) center center / 25p…

SQL:聚合函數(Aggregate Functions)

目錄 第一性原理出發思考 ——我們為什么需要聚合函數&#xff1f; 什么是聚合函數&#xff1f; 常見聚合函數 實例講解 &#x1f538; 1. COUNT() —— 計數 &#x1f538; 2. MAX() / MIN() —— 最大 / 最小值 &#x1f538; 3. SUM() —— 求和 &#x1f538; 4. …

海關總署廣東:廣東外貿一季度進出口2.14萬億元 同期增長4.2%

大灣區經濟網灣區財經報道&#xff0c;據海關總署廣東分署統計&#xff0c;今年一季度&#xff0c;廣東外貿進出口2.14萬億元&#xff0c;較去年同期&#xff08;下同&#xff09;增長4.2%&#xff0c;增速高于全國2.9個百分點。其中&#xff0c;出口1.34萬億元&#xff0c;增長…

MySQL中高級語法

Mysql高級語法 持續更新中… 1、EXISTS語法 一、基本語法結構 SELECT [列名] FROM [主表] WHERE [條件]AND EXISTS (SELECT 1 -- 子查詢內容無關&#xff0c;僅需占位符&#xff08;如1、*、X等&#xff09;FROM [子查詢表]WHERE [關聯條件] -- 必須與外層查詢關聯&#xf…

SpringBoot 調用deepseek

個人學習心得&#xff0c;僅供參考 軟件環境&#xff1a; JDK 17 你用JDK 11 無法支持SpringBoot 3SpringBoot 3 版本以上才支持spring aimavan 3.6.11.獲取Deepseek官網的API-key 官網&#xff1a;https://platform.deepseek.com/api_keys 2.創建項目 這樣創建 添加依賴…

性能測試面試題的詳細解答

以下是性能測試面試題的詳細解答&#xff1a; 1. 性能測試的流程是怎樣的&#xff1f; 性能測試流程通常包括以下幾個步驟&#xff1a; - **需求分析**&#xff1a;明確測試目標、性能指標&#xff08;如響應時間、吞吐量等&#xff09;。 - **環境搭建**&#xff1a;搭建測試環…

C++程序設計基礎實驗:C++對C的擴展特性與應用

C程序設計基礎實驗&#xff1a;C對C的擴展特性與應用 &#x1f525; 本文詳細講解C基礎實驗&#xff0c;包含C對C語言的擴充與增強特性&#xff0c;從零開始掌握函數重載、引用、指針等核心概念&#xff0c;附詳細代碼分析與運行結果。適合C初學者和有C語言基礎想學習C的同學&a…

量子神經網絡編譯器開發指南:從理論突破到產業落地全景解析

本文深度剖析IBM Qiskit 5.0量子經典混合編譯器的技術架構&#xff0c;詳解如何基于含噪量子處理器實現MNIST手寫數字分類任務&#xff08;準確率達89%&#xff09;。結合本源量子云、百度量子等國內平臺免費配額政策&#xff0c;系統性闡述量子神經網絡開發的技術路線與資源獲…

ESP32之本地HTTP服務器OTA固件升級流程,基于VSCode環境下的ESP-IDF開發(附源碼)

背景知識&#xff1a; 本實驗利用編譯鏈內Python內置的 HTTP 服務器&#xff0c;將升級包通過http發送給設備&#xff0c;實現OTA固件升級。 目錄 背景知識&#xff1a; 1.創建工程 1.1 創建OTA基礎工程 3.編寫、修改代碼 3.1 修改menuconfig配置文件 3.1.1 配置WiFi賬…

BootStrap:進階使用(其一)

今天我要講述的是在BootStrap中進一步使用的方法與代碼舉例; 導航條 作為在應用或網站中作為導航頁頭的響應式基礎組件。導航條在移動設備上可以折疊&#xff08;且可開可關&#xff09;&#xff0c;在視口&#xff08;viewport&#xff09;寬度增加時逐漸變為水平展開模式 …

ffmpeg無損轉格式的命令行

將ffmpeg.exe拖入命令行窗口 c:\users\zhangsan>D:\ffmpeg-2025-03-11\bin\ffmpeg.exe -i happy.mp4 -c:v copy -c:a copy 格式轉換后.mkv -c:v copy 僅做拷貝視頻,不重新編碼 -c:a copy 僅做拷貝音頻 ,不重新編碼

【Linux】深入理解Linux文件系統:從C接口到內核設計哲學

文章目錄 前言一、C語言中的文件接口1. 文件指針&#xff08;句柄&#xff09;FILE*以寫方式打開文件&#xff0c;若文件不存在會新建一個文件W寫入方式&#xff0c;在打開文件之前都會將文件內容全部清空追加寫方式&#xff0c;其用法與寫方法一致&#xff0c;不同在于a方法可…

國產品牌芯洲科技100V降壓芯片系列

SCT2A25采用帶集成環路補償的恒導通時間(COT)模式控制&#xff0c;大大簡化了轉換器的片外配置。SCT2A25具有典型的140uA低靜態電流&#xff0c;采用脈沖頻率調制(PFM)模式&#xff0c;它使轉換器在輕載或空載條件下實現高轉換效率。 芯洲科技100V降壓芯片系列提供豐富的48V系…

ctfshow-大賽原題-web702

因為該題沒有理解到位&#xff0c;導致看wp也一直出錯&#xff0c;特此反思一下。 參考yu22x師傅的文章 &#xff1a;CTFSHOW大賽原題篇(web696-web710)_ctfshow 大賽原題-CSDN博客 首先拿到題目&#xff1a; // www.zip 下載源碼 我們的思路就是包含一個css文件&#xff0c;…

LabVIEW技巧——獲取文件版本信息

獲取可執行文件&#xff08;exe&#xff09;版本信息的幾種方法 方法1. LabVIEW自帶函數 labview自帶了獲取文件版本號的VI&#xff0c;但是沒有開放到程序框圖的函數選板中&#xff0c;在該目錄下可以找到&#xff1a;...\LabVIEW 20xx\vi.lib\Platform\fileVersionInfo.llb…

三格電子——CAN 轉光纖(點對點)布線常見問題

1、CAN 布線 &#xff08;1&#xff09;H 接 H ,L 接 L &#xff08;2&#xff09;兩端設備掛 120 歐姆電阻 2、假如用點對點的 CAN 轉光纖現實遠程傳輸 &#xff08;1&#xff09;H 接 H ,L 接 L &#xff08;2&#xff09;光端機都掛 120 歐姆電阻 每個光端機掛的設備有一個加…

python進階: 深入了解調試利器 Pdb

Python是一種廣泛使用的編程語言&#xff0c;以其簡潔和可讀性著稱。在開發和調試過程中&#xff0c;遇到錯誤和問題是不可避免的。Python為此提供了一個強大的調試工具——Pdb&#xff08;Python Debugger&#xff09;。 Pdb是Python標準庫中自帶的調試器&#xff0c;可以幫助…

React 設計藝術:如何精確拆分組件接口,實現接口隔離原則

接口隔離原則 接口隔離原則&#xff08;Interface Segregation Principle&#xff0c;簡稱 ISP&#xff09;也是面向對象設計中的重要原則之一。它的核心思想是&#xff0c;一個類不應該依賴它不需要的接口。在 React 開發中&#xff0c;遵循接口隔離原則可以提高代碼的可維護性…

內部聊天軟件,BeeWorks-安全的企業內部通訊軟件

企業在享受數據便利的同時&#xff0c;如何保障企業數據安全已經成為無法回避的重要課題。BeeWorks作為一款專為企業設計的內部通訊軟件&#xff0c;通過全鏈路的安全能力升維&#xff0c;為企業提供了一個安全、高效、便捷的溝通協作平臺&#xff0c;全面保障企業數據安全。 …

【零基礎】基于 MATLAB + Gurobi + YALMIP 的優化建模與求解全流程指南

MATLAB Gurobi YALMIP 綜合優化教程&#xff08;進階&#xff09; 本教程系統介紹如何在 MATLAB 環境中使用 YALMIP 建模&#xff0c;并通過 Gurobi 求解器高效求解線性、整數及非線性優化問題。適用于工程、運營研究、能源系統等領域的高級優化建模需求。 一、工具概覽 1.…