Linux之信號量

目錄

信號量

信號量相關接口

創建信號量

初始化信號量?

等待信號量,P操作

發布信號量,V操作?

銷毀信號量

基于信號量的環形隊列下的生產者和消費者模型?

環形隊列

代碼實現


上期我們學習了線程同步的概念,掌握了基于阻塞隊列的生產者和消費者模型。基于阻塞隊列的生產者和消費者模型,三種關系,兩個角色,一個場所,現在我們要關注的就是這一個場所,在此模型中,我們把阻塞隊列稱為臨界資源,但是基于此模型,有且僅有這一個臨界資源,也就是說臨界資源的數目只有這一個。但是很多場景下臨界資源的數目并不只有一個,本期我們主要研究的就是臨界資源不只有一個的場景下的生產者和消費者模型。

信號量

我們之前學習了臨界資源的概念,臨界資源其實就是可以被多個執行流訪問的資源。上節課的生產者和消費者模型,只有超市這一個臨界資源。還有一個場景,就是電影院這個場景,在電影中,電影院的座位可以被多個顧客使用,所以電影院的座位就是臨界資源,且電影院的座位不單單只有一個,所以臨界資源是有多個的。那么信號量是什么呢?

信號量用于描述臨界資源的數目的大小,比如在電影院的模型下,信號量就可以表示座位的多少。?任何線程要訪問臨界資源,必須先申請信號量,訪問完臨界資源,必須釋放信號量。申請信號量我們稱為P操作,釋放信號量我們稱為V操作。

通過偽代碼為大家講述p操作和v操作。?

當然并不是所有臨界資源都可以用信號量來表示其數目的多少。當一個臨界資源可以被細分時,我們才可以用臨界資源來表示臨界資源的數目的多少,當一個臨界資源被分成了多個小的臨界資源時,此時就可以實現多個執行流共同訪問臨界資源,從而實現,多個執行流的并發,從而提高代碼的執行效率。

信號量相關接口

信號量的接口與互斥鎖接口和條件變量接口類似。

創建信號量

sem_t? sem;? ? ? ?//創建信號量?

初始化信號量?

int sem_init(sem_t *sem, int pshared, unsigned int value);? ? ? ? ? //初始化信號量

sem為創建的信號量的地址;pshared,0表示線程間共享,非0表示進程間共享;value表示信號量的初始值。

等待信號量,P操作

int sem_wait(sem_t *sem);? ? ? ? ? ?//P()

等待信號量,表示申請信號量,要使用資源。將信號量減1。

發布信號量,V操作?

sem_post(sem_t *sem);? ? ? ? ? //V()

發布信號量,表示資源使用完畢,可以歸還資源了。將信號量值加1。

銷毀信號量

int sem_destroy(sem_t *sem);? ? ? ? ? ?//銷毀信號量??

基于信號量的環形隊列下的生產者和消費者模型?

環形隊列

上圖為一個環形隊列,有生產者和消費者兩個角色,環形隊列為一個大的臨界資源,這個大的臨界資源有被分成了多個小部分,為多份小的臨界資源。?

代碼實現

生產者往環形隊列中生產數據,消費者從環形隊列中消費數據。生產者每生產一個數據前進一格,當生產者和消費者相遇時,要么是環形隊列為空,要么是環形隊列中的數據已滿。基于此,我們對基于環形隊列的生產者和消費者模型設立兩個規則。

規則一:生產者不能把消費者逃一圈,因為一旦套了一圈,勢必會造成相遇時,生產者和消費者所處的環形隊列的那一塊空間中數據的覆蓋,造成數據丟失。

規則二:因為剛開始環形隊列是為空的,所以剛開始一定是生產者先生產,然后再是消費者再進行消費,正是基于此,往后消費者的位置一定是不能超過生產者的。

生產者看重的是環形隊列中的空白位置的數目,而消費者看重的是環形隊列中數據的數目。所以創建兩個信號量,一個信號量描述環形隊列中空位置的數目,一個信號量描述環形隊列中數據的數目。

代碼實現如下。

?RingQueue.hpp

#include <iostream>
#include <vector>
#include <semaphore.h>namespace yjd
{const int DefaultCapacity = 10;template <class T>class RingQueue{public:RingQueue(const int &capacity = DefaultCapacity): _v(capacity){_capacity = capacity;sem_init(&_blank_sem, 0, 10);sem_init(&_data_sem, 0, 0);_c_step = _p_step = 0;}~RingQueue(){sem_destroy(&_blank_sem);sem_destroy(&_data_sem);}void push(T &data){sem_wait(&_blank_sem);_v[_p_step] = data;sem_post(&_data_sem);_p_step++;_p_step % _capacity;}void pop(T *data){sem_wait(&_data_sem);*data = _v[_c_step];sem_post(&_blank_sem);_c_step++;_c_step%_capacity;}private:std::vector<T> _v;int _capacity;// 描述空位置的數目sem_t _blank_sem;// 描述數據的數目sem_t _data_sem;int _p_step;int _c_step;};
}

整個代碼的邏輯為,生產者先生產數據,然后消費者消費數據。生產者要生產數據,先申請一個空位置信號量,空位置信號量減1,然后生產數據,生產完數據之后,數據信號量加1;消費者消費數據時,先申請數據信號量,數據信號量減1,消費完數據之后,多了一個空位置,空位置信號量加1。

?RingCP.cc

#include "RingQueue.hpp"
#include <pthread.h>
#include <unistd.h>
#include <time.h>using namespace yjd;void *producter(void *args)
{RingQueue<int> *rq = (RingQueue<int> *)args;while (true){int data = rand() % 20 + 1;rq->push(data);std::cout << "生產者生產數據 " << data << std::endl;}
}void *consumer(void *args)
{RingQueue<int> *rq = (RingQueue<int> *)args;while (true){int data = 0;rq->pop(&data);std::cout << "消費者消費數據 " << data << std::endl;sleep(1);}
}int main()
{pthread_t c;pthread_t p;RingQueue<int> *rq = new RingQueue<int>();srand((long long)time(nullptr));pthread_create(&c, nullptr, consumer, (void *)rq);pthread_create(&p, nullptr, producter, (void *)rq);pthread_join(c, nullptr);pthread_join(p, nullptr);return 0;
}

運行結果如下。

通過運行結果可知,我們通過使用信號量和喚醒隊列,實現了生產和消費者的同步。??

以上便是本期信號量的相關知識點。

本期內容到此結束 ^_^

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

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

相關文章

【電子通識】PWM驅動讓有刷直流電機恒流工作

電機的典型驅動方法包括電壓驅動、電流驅動以及PWM驅動。本文將介紹采用PWM驅動方式的恒流工作。 首先介紹的是什么是PWM驅動的電機恒流工作&#xff0c;其次是PWM驅動電機恒流工作時電路的工作原理。 PWM驅動 當以恒定的電流驅動電機時&#xff0c;電機會怎樣工作呢&#xff1…

非docker方式部署openwebui過程記錄

之前一直用docker方式部署openwebui&#xff0c;結果這東西三天兩頭升級&#xff0c;我這一升級拉取docker鏡像硬盤空間嗖嗖的占用&#xff0c;受不了&#xff0c;今天改成了直接部署&#xff0c;以下是部署過程記錄。 一、停止及刪除沒用的docker鏡像占用的硬盤空間 docker s…

[python3]Excel解析庫-xlwings

xlwings 是一個強大的 Python 庫&#xff0c;它允許你直接與 Microsoft Excel 進行交互。通過 xlwings&#xff0c;你可以輕松地在 Python 腳本或 Jupyter Notebook 中讀取、寫入和操作 Excel 文件&#xff0c;而無需手動打開 Excel 應用程序。此外&#xff0c;xlwings 還支持將…

Kafka 消費者專題

目錄 消費者消費者組消費方式消費規則獨立消費主題代碼示例&#xff08;極簡&#xff09;代碼示例&#xff08;獨立消費分區&#xff09; offset自動提交代碼示例&#xff08;自動提交&#xff09;手動提交代碼示例&#xff08;同步&#xff09;代碼示例&#xff08;異步&#…

【游戲設計原理】47 - 超游戲思維

對于這條原理&#xff0c;我首先想到的是開放世界&#xff0c;或者探索性游戲&#xff0c;這是最能包容各類玩家的游戲類型。這類游戲定義了基本規則&#xff0c;玩家的可操作性很強。就像上圖里的沙池一樣&#xff0c;里面有滑梯&#xff0c;是規則性比較明確的&#xff0c;而…

奧迪TT MK1(初代奧迪TT、第一代奧迪TT)儀表盤故障/不精準/水溫/剩余油量不準,如何修復、測試、復位?

故障現象 水溫不準&#xff0c;冷啟動就130℃汽油加滿&#xff0c;指針依然在中間偏左的位置 如下圖&#xff1a; 診斷過程 通過VAG KKL 409 USB OBD接口讀取水溫和油位數值正常&#xff0c;故判斷是儀表指針馬達損壞或需要重置指針位置 維修步驟 推薦選擇CH340&#xff08;老…

Nginx——服務器端集群搭建與擴展模塊(五/五)

目錄 1.Nginx實現服務器端集群搭建1.1.Nginx 與 Tomcat 部署1.1.1.環境準備 (Tomcat)1.1.2.環境準備 (Nginx) 1.2.Nginx實現動靜分離1.2.1.概述1.2.2.需求分析1.2.3.動靜分離實現步驟 1.3.Nginx 實現 Tomcat 集群搭建1.4.Nginx 高可用解決方案1.4.1.概述1.4.2.Keepalived 介紹1…

輕量級通信協議 JSON-RPC 2.0 詳解

目錄 JSON-RPC 2.0 簡介 請求對象 響應對象 通知 批量請求 錯誤碼 使用場景 文檔和版本控制 社區和支持 小結 參考資料 JSON-RPC 2.0 簡介 JSON-RPC (JavaScript Object Notation - Remote Procedure Call) 是一種輕量級的遠程過程調用協議&#xff0c;使用 JSON&am…

ffmpeg之h264格式轉yuv

h264格式轉yuv詳細步驟 初始化FFmpeg庫&#xff1a;通過av_register_all()來初始化必要的組件。打開輸入文件并查找解碼器&#xff1a;使用avformat_open_input和 avcodec_find_decoder 打開H.264文件&#xff0c;并查找視頻流。分配并配置解碼上下文&#xff1a;使用 avcodec…

創建VUE腳手架

1.輸入 npm create vuelatest2.創建完成

vue3如何實現防抖?

第一 防抖就是我們設置一個調用時間&#xff0c;點擊后設置時間開始倒計時&#xff0c;如果再次點擊會重新倒計時 npm或yarn安裝&#xff1a; npm install lodash <template><div click"debouncedInputHandler"><button>打印</button>…

JavaWeb開發(六)XML介紹

1. XML介紹 1.1. 什么是XML &#xff08;1&#xff09;XML 指可擴展標記語言(EXtensible Markup Language)XML 是一種很像HTML的標記語言。 ??&#xff08;2&#xff09;XML 的設計宗旨是傳輸數據(目前主要是作為配置文件)&#xff0c;而不是顯示數據。 ??&#xff08;3&a…

用shell把(1到100)100個整數寫入到二進制文件

author: hjjdebug date: 2025年 01月 05日 星期日 16:14:41 CST description: 用shell把(1到100)100個整數寫入到二進制文件 1. 問題分析(需求分析) 在c語言下, 整數int 是按4個字節存儲的,能表示最大0xffffffff的范圍 但shell并沒有一條命令能夠實現把一個整數寫入二進制文件…

SpringBoot下載文件的幾種方式

小文件&#xff1a;直接將文件一次性讀取到內存中&#xff0c;文件大可能會導致OOM GetMapping("/download1")public void download1(HttpServletResponse response) throws IOException {// 指定要下載的文件File file new File("C:\\Users\\syd\\Desktop\\do…

Flink使用

Window下啟動支持 下載或復制老版本的放在bin目錄下即可&#xff1b; flink.bat echo off setlocalSET bin%~dp0 SET FLINK_HOME%bin%.. SET FLINK_LIB_DIR%FLINK_HOME%\lib SET FLINK_PLUGINS_DIR%FLINK_HOME%\pluginsSET JVM_ARGS-Xmx512mSET FLINK_JM_CLASSPATH%FLINK_LI…

Python基礎知識回顧-數據結構

Tuple 在 Python 中&#xff0c;我們經常使用 Tuple 來將相關數據分組。Tuple 指的是有序且不可變的元素集合。 形式&#xff1a;通常以逗號分隔的元素寫在括號"() "中。 數據類型和索引&#xff1a;包含 String、整數和浮點數&#xff0c;并使用正索引和負索引訪問…

8. C++ 面向對象之特性一(封裝)

面向對象主要包括三大類&#xff1a;封裝&#xff0c;繼承&#xff0c;多態 1.類和對象 c認為&#xff0c;萬物皆為對象&#xff0c;對象上有其屬性和行為 人可以作為對象&#xff0c;屬性有姓名、年齡、身高、體重...&#xff0c;行為有走、跑、跳、吃飯、唱歌... 車也可以作…

WebRtc02:WebRtc架構、目錄結構、運行機制

整體架構 WebRtc主要分為三層&#xff1a; CAPI層&#xff1a;外層調用Session管理核心層&#xff1a;包括視頻引擎、音頻引擎、網絡傳輸 可由使用者重寫視頻引擎&#xff1a;編解碼器、視頻緩存、視頻增強音頻引擎&#xff1a;編解碼器、音頻緩存、回音消除、降噪傳輸&#x…

【Qt】快速添加對應類所需的頭文件包含

快速添加對應類所需的頭文件包含 一&#xff0c;簡介二&#xff0c;操作步驟 一&#xff0c;簡介 本文介紹一下&#xff0c;如何快速添加對應類所需要包含的頭文件&#xff0c;可以提高開發效率&#xff0c;供參考。 二&#xff0c;操作步驟 以QTime類為例&#xff1a; 選中…

Apache MINA 反序列化漏洞CVE-2024-52046

漏洞描述&#xff1a; Apache MINA 是一個功能強大、靈活且高性能的網絡應用框架。它通過抽象網絡層的復雜性&#xff0c;提供了事件驅動架構和靈活的 Filter 鏈機制&#xff0c;使得開發者可以更容易地開發各種類型的網絡應用。 Apache MINA 框架的 ObjectSerializationDeco…