【多線程】線程同步--條件變量的原理及其使用

文章目錄

  • 前言
  • 線程同步的基本概念
    • 條件變量
      • 定義條件變量
      • 初始化條件變量
      • 銷毀條件變量
      • 等待條件(重要)
      • 喚醒等待
      • 簡單運用
      • 常見使用條件變量的格式

前言

線程同步意味著在多線程并發執行中,協調線程之間的執行順序,以確保共享資源被正確訪問和修改。線程同步的維護本質就是在安排線程之間的執行順序。那么在linux中是如何維護線程同步的呢?本篇文章將圍繞這個為題展開敘述。

線程同步的基本概念

下面介紹一些有關線程同步的基本概念。

條件變量

當一個線程互斥的訪問某個變量,即訪問臨界資源時給臨界區上互斥鎖,這個時候其它線程只能等待。那什么時候其它線程可以繼續申請臨界資源呢?我們希望當一個線程使用完臨界資源后,正在等待的線程能夠知道這一事件的發生從而重新申請資源,而不是一直重復申請這個動作

就像一個鬧鐘,當鬧鐘響了之后我們就知道該起床了,而不是睡一下又看下時間。

條件變量提供一種線程通信的方法,使得一個線程可以等待另一個線程滿足某種條件后再繼續執行。具體的,我們將這種通知一個線程繼續執行的動作稱為喚醒

于是,借助條件變量,我們就能實現協調線程之間訪問臨時資源的順序性。

同時線程庫給我們提供了一些接口用來操作條件變量,下面介紹一些常見的關于條件變量的操作。(頭文件都是pthread.h

定義條件變量

初始化條件變量

  1. 動態初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr); 
  • cond :要初始化的條件變量
  • attr:條件變量的屬性,通常是NULL
  1. 靜態初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

銷毀條件變量

int pthread_cond_destroy(pthread_cond_t *cond);

銷毀某個條件變量,成功返回0,失敗返回錯誤代碼
在這里插入圖片描述

等待條件(重要)

如果當前線程沒有申請到臨界資源,該線程可以選擇等待。

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

在調用該函數時,互斥鎖mutex必須被鎖住,并等待喚醒。喚醒之后線程重新鎖住互斥鎖并繼續執行。值得注意的是,pthread_cond_wait函數首先會解鎖與之關聯的互斥鎖mutex,這也是為什么使用該函數時mutex必須是被鎖住的。然后調用該函數的線程進入阻塞狀態,直到被喚醒。最后,條件變量被通知之后,pthread_cond_wait重新鎖定互斥鎖mutex
對于該函數提出以下問題:

  • 為什么要在pthread_cond_wait中傳入互斥鎖
    • 在調用 pthread_cond_wait 時,互斥鎖是已經鎖住的,確保沒有其他線程可以修改共享資源。
    • pthread_cond_wait 在進入等待狀態之前會自動釋放互斥鎖,使得其他線程可以修改條件。
    • 當線程被喚醒后,pthread_cond_wait 會重新獲得互斥鎖,然后再繼續執行,因為此時還在臨界區,還會訪問臨界資源。

喚醒等待

  1. 喚醒某個線程
int pthread_cond_signal(pthread_cond_t *cond);

喚醒一個等待在條件變量 cond 上的線程。如果有多個線程在等待條件變量,具體喚醒哪一個線程是不確定的。
成功返回0,失敗則返回錯誤碼

  1. 喚醒所有正在等待該條件變量的線程
int pthread_cond_broadcast(pthread_cond_t *cond);

喚醒所有等待在條件變量 cond 上的線程。同樣成功返回0,失敗則返回錯誤碼。

簡單運用

下面我們使用條件變量和互斥鎖來設計一個簡單的代碼樣例

#include <iostream>
#include <unistd.h>
#include <pthread.h>using namespace std;pthread_cond_t cond;
pthread_mutex_t mutex;void *r1(void *arg) // 等待函數,執行該函數的線程一直處于while (true)
{pthread_cond_wait(&cond, &mutex);cout << "被喚醒" << endl;return arg;
}void *r2(void *arg) // 喚醒函數,執行該函數的線程一直嘗試喚醒某個等待的線程
{while (true){pthread_cond_signal(&cond);cout << "喚醒某個線程" << endl;sleep(1);}
}int main()
{pthread_t t1, t2; // 定義兩個線程pthread_cond_init(&cond, NULL);   // 初始化條件變量pthread_mutex_init(&mutex, NULL); // 初始化互斥鎖pthread_create(&t1, NULL, r1, NULL); // 創建線程并分配執行函數pthread_create(&t1, NULL, r2, NULL);pthread_join(t1, NULL); // 等待線程退出pthread_join(t2, NULL);pthread_mutex_destroy(&mutex); // 銷毀互斥鎖和條件變量pthread_cond_destroy(&cond);return 0;
}

在這里插入圖片描述

常見使用條件變量的格式

  • 等待條件代碼:
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/diannao/44393.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/44393.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/44393.shtml

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

相關文章

Kylin系列(三)安裝與配置:搭建你的第一個 Kylin 環境

目錄 1. Kylin 簡介 1.1 Kylin的核心特點 1.2 適用場景 2. 環境準備 2.1 硬件要求 2.2 軟件依賴 3. 安裝與配置 3.1 安裝JDK 3.2 安裝Hadoop 3.2.1 下載并解壓Hadoop 3.2.2 配置Hadoop環境變量 3.2.3 配置Hadoop文件 3.2.4 格式化HDFS并啟動Hadoop服務 3.3 安裝H…

hive架構詳解:HQL案例解析(第15天)

系列文章目錄 一、Hive基礎架構&#xff08;重點&#xff09; 二、Hive數據庫,表操作&#xff08;重點&#xff09; 三、Hadoop架構詳解(hdfs)&#xff08;補充&#xff09; 四、Hive環境準備&#xff08;操作&#xff09;(補充) 文章目錄 系列文章目錄前言一、Hive基礎架構1、…

4. 小迪安全v2023筆記 javaEE應用

4. 小迪安全v2023筆記 javaEE應用 ? 大體上跟隨小迪安全的課程&#xff0c;本意是記錄自己的學習歷程&#xff0c;不能說是完全原創吧&#xff0c;大家可以關注一下小迪安全。 若有冒犯&#xff0c;麻煩私信移除。 默認有java基礎。 文章目錄 4. 小迪安全v2023筆記 javaEE應…

分塊

分塊 分塊是將線段樹的懶標記方法一般化&#xff0c;可證明通常情況下以 n \sqrt n n ?分塊是最優解。 分塊思想核心&#xff1a; 整塊打包維護 碎塊逐個枚舉 int len,num;//len:每塊長度,num:分塊數量 int begin[],end[],pos[],sum[],add[];//begin,end:每塊的始末下標 po…

linux下安裝cutecom串口助手;centos安裝cutecom串口助手;rpm安裝包安裝cutecom串口助手

在支持apt-get的系統下安裝 在終端命令行中輸入&#xff1a; sudo apt-get install cutecom 安裝好后輸入 sudo cutecom 就可以了 關于如何使用&#xff0c;可以看這個https://www.cnblogs.com/xingboy/p/14388610.html 如果你的電腦不支持apt-get。 那我們就通過安裝包…

‘wget‘ 不是內部或外部命令,也不是可運行的程序

在Windows環境下創建了虛擬環境并安裝了wget包&#xff0c;但在使用該命令的時候仍然報錯&#xff0c;‘wget’ 不是內部或外部命令,也不是可運行的程序 解決方案&#xff1a; 去官網下載對應位數的.exe文件&#xff0c;將其放在C:\Windows\System32目錄下即可, 別下錯版本&a…

寶塔面板部署Flask項目教程(最新版)

本教程適用于最新版的寶塔&#xff01;&#xff01;&#xff01; 本教程適用于最新版的寶塔&#xff01;&#xff01;&#xff01; 本教程適用于最新版的寶塔&#xff01;&#xff01;&#xff01; 1 準備 1.1 依賴文件 在你的項目根目錄下生成一個依賴文件&#xff0c;執行…

美業收銀系統怎么選?哪些功能實用?美業門店管理系統|拓客系統

選擇美業會員系統時&#xff0c;你可以考慮以下幾個方面的功能來確定哪些對你最實用&#xff1a; 1.會員管理&#xff1a; 系統應該能夠輕松管理會員資料、積分、消費記錄等信息&#xff0c;以便更好地了解客戶需求并提供個性化服務。 2.促銷與營銷工具&#xff1a; 包括發…

Perl中追蹤文件脈動:文件系統事件通知機制全解析

&#x1f4e1; Perl中追蹤文件脈動&#xff1a;文件系統事件通知機制全解析 在Perl編程中&#xff0c;文件系統事件通知機制允許程序響應文件或目錄的變化&#xff0c;例如文件的創建、刪除、修改等。這種機制對于實現如文件監控、數據同步、自動化任務等應用至關重要。本文將…

電商開通云賬戶分賬系統實現功能場景

什么是虛擬銀行賬戶: 銀行虛擬戶也稱為銀行虛擬公戶&#xff0c;是指企業或機構在銀行開設的一種特殊類型的銀行賬戶。它與普通銀行賬戶不同&#xff0c;虛擬公戶通常不涉及實際的資金流動&#xff0c;而主要用于管理和監控資金流向&#xff0c;以及實現特定的業務和財務目標。…

vue3項目安裝和使用element-plus

第一步&#xff1a;安裝 npm install element-plus --save 第二步&#xff1a;在main.js文件夾上引入 import { createApp } from vue import ./style.css import ElementPlus from element-plus import element-plus/dist/index.css import App from ./App.vueconst app c…

3D云渲染工具對決:Maya與Blender的性能和功能深度比較

3D建模和動畫制作已成為數字領域不可或缺的一環&#xff0c;無論是在影視特效的震撼場面&#xff0c;還是在游戲角色的生動表現&#xff0c;3D技術都扮演著至關重要的角色。而在這一領域&#xff0c;Maya和Blender這兩款軟件&#xff0c;以其強大的功能和廣泛的應用&#xff0c…

【JavaEE】進程

目錄 一.馮諾依曼體系結構 二.CPU的核心概念 核心數 頻率&#xff08;Clock Speed 或時鐘頻率&#xff09; 如何選擇合適的CPU 三.指令的執行 1.什么是指令 1.取指令 2.解析指令 3.執行指令 4.訪問內存&#xff08;Memory&#xff09;: 5.寫回結果&#xff08;Write…

視頻解碼故障案例兩則

案例1 綠邊 故障分析&#xff1a; 這個能明顯看到視頻上方出現綠色半透明邊帶。這說明Y數據正常。UV數據不正常。 它顯然與視頻幀的垂直分辨率設置有關。 UV數據和Y數據是連續放置的&#xff0c;如果上方出現彩色數據失調&#xff0c;說明這部分數據實際仍然是Y數據。也就是…

為什么我在go語言里從前端接收到的參數是數字28546.123456,但是我不能使用float32只能使用float64呢?

在 Go 語言中&#xff0c;當你從前端&#xff08;例如通過 HTTP 請求&#xff09;接收數據時&#xff0c;這些數據通常以字符串的形式到達后端。然后&#xff0c;后端需要將這些字符串解析或轉換為適當的類型&#xff0c;比如 float32 或 float64。 然而&#xff0c;如果你發現…

JAVASE進階day08(Map雙列集合)

HashMap 1.HashMap基本使用 package com.lu.day08.map;import java.util.HashMap; import java.util.Map; import java.util.Set;public class MapDome {public static void main(String[] args) {HashMap<String , String> map new HashMap<>();//添加后者修改-…

H264視頻編碼中Annex B 格式介紹

Annex B 格式是 H.264 (也稱為 AVC) 視頻編碼標準中的一種數據表示格式&#xff0c;用于將視頻數據從編碼器傳輸到解碼器。它主要用于流媒體傳輸和文件存儲。 文章目錄 Annex B 格式的定義Annex B 格式的主要特點Annex B 與其他格式的對比Annex B 格式示例將 H.264 數據從 MP4…

查詢(q_proj)、鍵(k_proj)和值(v_proj)投影具體含義

查詢(q_proj)、鍵(k_proj)和值(v_proj)投影&#xff0c;這些投影是自注意力機制的核心組件&#xff0c;特別是在Transformer架構中。 讓我們通過一個簡化的例子來說明&#xff1a; import numpy as np# 假設輸入維度是4&#xff0c;注意力頭數是2 input_dim 4 num_heads 2 …

每天一道Java面試題系列之--Spring如何解決循環依賴問題

面試題&#xff1a;Spring如何解決循環依賴問題&#xff1f; 問題背景&#xff1a; 在Spring框架中&#xff0c;循環依賴通常發生在單例&#xff08;Singleton&#xff09;作用域的bean之間。當兩個或多個bean在它們的構造函數中相互引用時&#xff0c;Spring容器在創建這些b…

電腦32位和62位是什么意思

在現代計算機世界中&#xff0c;32位和64位是兩個常見的術語&#xff0c;但許多用戶可能不太清楚它們的確切含義以及它們之間的區別。本文將詳細介紹32位和64位計算機的基本概念、如何查看您的計算機是32位還是64位&#xff0c;以及它們對用戶的實際影響。 32位與64位的基本概…