【Linux】多線程_7

文章目錄

  • 九、多線程
    • 8. POSIX信號量
      • 根據信號量+環形隊列的生產者消費者模型代碼
      • 結果演示
  • 未完待續


九、多線程

8. POSIX信號量

POSIX信號量和SystemV信號量作用相同,都是用于同步操作,達到無沖突的訪問共享資源目的。 但POSIX可以用于線程間同步。
創建多線程的信號量:
在這里插入圖片描述
銷毀多線程之間的信號量:
在這里插入圖片描述
對信號量做P操作(申請資源):
在這里插入圖片描述
對信號量做V操作(釋放資源):
在這里插入圖片描述

根據信號量+環形隊列的生產者消費者模型代碼

Makefile

cp_ring:Main.ccg++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -f cp_ring

Thread.hpp

#ifndef __THREAD_HPP__
#define __THREAD_HPP__#include <iostream>
#include <string>
#include <unistd.h>
#include <functional>
#include <pthread.h>namespace ThreadModule
{template<typename T>using func_t = std::function<void(T&, const std::string& name)>;template<typename T>class Thread{public:void Excute(){_func(_data, _threadname);}public:Thread(func_t<T> func, T& data, const std::string &name="none-name"): _func(func), _data(data), _threadname(name), _stop(true){}static void *threadroutine(void *args){Thread<T> *self = static_cast<Thread<T> *>(args);self->Excute();return nullptr;}bool Start(){int n = pthread_create(&_tid, nullptr, threadroutine, this);if(!n){_stop = false;return true;}else{return false;}}void Detach(){if(!_stop){pthread_detach(_tid);}}void Join(){if(!_stop){pthread_join(_tid, nullptr);}}std::string name(){return _threadname;}void Stop(){_stop = true;}~Thread() {}private:pthread_t _tid;std::string _threadname;T& _data;func_t<T> _func;bool _stop;};
}#endif

RingQueue.hpp

#pragma once#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>// 環形隊列類模板
template<class T>
class RingQueue
{
private:// 申請資源void P(sem_t& sem){sem_wait(&sem);}// 釋放資源void V(sem_t& sem){sem_post(&sem);}// 加鎖void Lock(pthread_mutex_t& mutex){pthread_mutex_lock(&mutex);}// 解鎖void Unlock(pthread_mutex_t& mutex){pthread_mutex_unlock(&mutex);}
public:RingQueue(int cap):_cap(cap),_ring_queue(cap),_prodeucer_step(0),_consumer_step(0){sem_init(&_room_sem, 0, _cap);sem_init(&_data_sem, 0, 0);pthread_mutex_init(&_prodeucter_mutex, nullptr);pthread_mutex_init(&_consumer_mutex, nullptr);}// 生產者的入隊列函數void Enqueue(const T& in){// 申請空間資源P(_room_sem);// 加鎖Lock(_prodeucter_mutex);// 入隊列_ring_queue[_prodeucer_step++] = in;// 環形,繞一圈_prodeucer_step %= _cap;// 解鎖Unlock(_prodeucter_mutex);// 釋放數據資源V(_data_sem);}// 消費者的出隊列函數void Pop(T* out){// 申請數據資源P(_data_sem);// 加鎖Lock(_consumer_mutex);// 出隊列*out = _ring_queue[_consumer_step++];_consumer_step %= _cap;// 解鎖Unlock(_consumer_mutex);// 釋放空間資源V(_room_sem);}~RingQueue(){sem_destroy(&_room_sem);sem_destroy(&_data_sem);pthread_mutex_destroy(&_prodeucter_mutex);pthread_mutex_destroy(&_consumer_mutex);}
private:// 數組模擬環形隊列std::vector<T> _ring_queue;// 容量int _cap;// 生產者和消費者的位置指針int _prodeucer_step;int _consumer_step;// 信號量sem_t _room_sem;sem_t _data_sem;// 互斥鎖pthread_mutex_t _prodeucter_mutex;pthread_mutex_t _consumer_mutex;
};

Task.hpp

#pragma once#include <iostream>
#include <functional>using Task = std::function<void()>;void Download()
{std::cout << "Downloading..." << std::endl;
}

Main.cc

#include "RingQueue.hpp"
#include "Thread.hpp"
#include "Task.hpp"
#include <string>
#include <vector>
#include <unistd.h>using namespace ThreadModule;
// 創建類型別名
using ringqueue_t = RingQueue<Task>;// 消費者線程
void Consumer(ringqueue_t& rq, const std::string& name)
{while (true){// 獲取任務Task t;rq.Pop(&t);std::cout << "Consumer " << name << " : ";// 執行任務t();}
}// 生產者線程
void Productor(ringqueue_t& rq, const std::string& name)
{while (true){// 發布任務rq.Enqueue(Download);std::cout << "Productor " << name << " : " << "Download task" << std::endl;sleep(1);}
}// 啟動線程
void InitComm(std::vector<Thread<ringqueue_t>>* threads, int num, ringqueue_t& rq, func_t<ringqueue_t> func)
{for (int i = 0; i < num; i++){// 創建一批線程std::string name = "thread-" + std::to_string(i + 1);threads->emplace_back(func, rq, name);}
}// 創建消費者線程
void InitConsumer(std::vector<Thread<ringqueue_t>>* threads, int num, ringqueue_t& rq)
{InitComm(threads, num, rq, Consumer);
}// 創建生產者線程
void InitProductor(std::vector<Thread<ringqueue_t>>* threads, int num, ringqueue_t& rq)
{InitComm(threads, num, rq, Productor);
}// 等待所有線程結束
void WaitAllThread(std::vector<Thread<ringqueue_t>>& threads)
{for (auto& thread : threads){thread.Join();}
}// 啟動所有線程
void StartAll(std::vector<Thread<ringqueue_t>>& threads)
{for (auto& thread : threads){thread.Start();}
}int main()
{// 創建阻塞隊列,容量為5ringqueue_t* rq = new ringqueue_t(10);// 創建線程std::vector<Thread<ringqueue_t>> threads;// 創建 1個消費者線程InitConsumer(&threads, 1, *rq);// 創建 1個生產者線程InitProductor(&threads, 1, *rq);// 啟動所有線程StartAll(threads);// 等待所有線程結束WaitAllThread(threads);return 0;
}

結果演示

在這里插入圖片描述
這里演示的是單生產者單消費者的模型,可以在主函數改成多生產者多消費者的模型。


未完待續

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

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

相關文章

什么ISP?什么是IAP?

做單片機開發的工程師經常會聽到兩個詞&#xff1a;ISP和IAP&#xff0c;但新手往往對這兩個概念不是很清楚&#xff0c;今天就來和大家聊聊什么是ISP&#xff0c;什么是IAP&#xff1f; 一、ISP ISP的全稱是&#xff1a;In System Programming&#xff0c;即在系統編程&…

如何申請抖音本地生活服務商?3種方式優劣勢分析!

隨著多家互聯網大廠在本地生活板塊的布局力度不斷加大&#xff0c;以抖音為代表的頭部互聯網平臺的本地生活服務商成為了創業賽道中的大熱門&#xff0c;與抖音本地生活服務商怎么申請等相關的帖子&#xff0c;更是多次登頂創業者社群的話題榜單。 就目前的市場情況來看&#x…

Go語言--廣播式并發聊天服務器

實現功能 每個客戶端上線&#xff0c;服務端可以向其他客戶端廣播上線信息&#xff1b;發送的消息可以廣播給其他在線的客戶支持改名支持客戶端主動退出支持通過who查找當前在線的用戶超時退出 流程 變量 用戶結構體 保存用戶的管道&#xff0c;用戶名以及網絡地址信息 typ…

ARM功耗管理之功耗數據與功耗收益評估

安全之安全(security)博客目錄導讀 思考&#xff1a;功耗數據如何測試&#xff1f;功耗曲線&#xff1f;功耗收益評估&#xff1f; UPF的全稱是Unified Power Format&#xff0c;其作用是把功耗設計意圖&#xff08;power intent&#xff09;傳遞給EDA工具&#xff0c; 從而幫…

vscode OpenCV環境搭建

cmake 官網https://cmake.org/files/ 環境變量D:\Program Files\CMake\bin w64devkit 官網https://github.com/skeeto/w64devkit/tags 環境變量D:\Program Files\w64devkit\bin minGW32-make 拷貝并重命名為make OpenCV 在執行完后&#xff0c;把關于python的都給取消勾選…

mybatis-plus映射mysql的json類型的字段

一、對json里面內容建立實體類 Data AllArgsConstructor NoArgsConstructor public class RouteMetaEntity {private String title;private Boolean affix;private Boolean isAlwaysShow; }二、主類做映射 TableField(typeHandler JacksonTypeHandler.class)private RouteMe…

Codeforces Round 958 (Div. 2)補題

文章目錄 A題 (拆分多集)B題(獲得多數票)C題&#xff08;固定 OR 的遞增序列&#xff09; A題 (拆分多集) 本題在賽時卡的時間比較久&#xff0c;把這題想復雜了&#xff0c;導致WA了兩次。后來看明白之后就是將n每次轉換成k-1個1&#xff0c;到最后分不出來k-1個1直接一次就能…

Hive的基本操作(查詢)

1、基礎查詢 基本語法 select 字段列表|表達式|子查詢 from 表(子查詢|視圖|臨時表|普通表) where [not] 條件A and|or 條件B --先&#xff1a;面向原始行進行篩選 group by 字段A[,字段B,...] > 分組【去重處理】 having 聚合條件(非原始字段條件) --再&#x…

JMeter案例分享:通過數據驗證的錯誤,說說CSV數據文件設置中的線程共享模式

前言 用過JMeter參數化的小伙伴&#xff0c;想必對CSV Data Set Config非常熟悉。大家平時更關注變量名稱&#xff0c;是否忽略首行等參數&#xff0c;其余的一般都使用默認值。然而我最近遇到一個未按照我的預想讀取數據的案例&#xff0c;原因就出在最后一個參數“線程共享模…

深度學習中激活函數的演變與應用:一個綜述

摘要 本文全面回顧了深度學習中激活函數的發展歷程,從早期的Sigmoid和Tanh函數,到廣泛應用的ReLU系列,再到近期提出的Swish、Mish和GeLU等新型激活函數。深入分析了各類激活函數的數學表達、特點優勢、局限性以及在典型模型中的應用情況。通過系統的對比分析,本文探討了激…

樹莓派配置vsftpd主動模式

sudo apt-get install vsftpd /etc/vsftpd.conf anonymous_enableNO # 禁用匿名用戶 local_enableYES # 允許本地用戶登錄 write_enableYES # 允許修改權限 #chroot_local_userYES # 將用戶限制在其主目錄 systemctl restart vsftpd sudo adduser ftpuser sudo pa…

詳解MySQL中的遞歸查詢

MySQL中的遞歸查詢主要通過WITH RECURSIVE語句來實現&#xff0c;這在處理具有層級關系或樹形結構的數據時非常有用。下面將通過一個具體的例子來詳細解釋如何在MySQL中使用遞歸查詢。 示例場景 假設我們有一個部門表&#xff08;departments&#xff09;&#xff0c;其中包含…

昇思訓練營打卡第二十五天(RNN實現情感分類)

RNN&#xff0c;即循環神經網絡&#xff08;Recurrent Neural Network&#xff09;&#xff0c;是一種深度學習模型&#xff0c;特別適用于處理序列數據。以下是對RNN的簡要介紹&#xff1a; RNN的特點&#xff1a; 記憶性&#xff1a;與傳統的前饋神經網絡不同&#xff0c;R…

老板新招的牛人,竟然用1天搭建了一套完整的倉庫管理系統!

倉儲管理系統是什么&#xff1f; 倉儲管理系統&#xff08;WMS&#xff09;是一個全面的軟件解決方案&#xff0c;旨在幫助企業優化倉庫管理流程、管理和控制日常倉庫運營。通過數學模型和信息手段&#xff0c;對倉庫管理的各個環節進行優化和調控&#xff0c;涵蓋了從貨物入庫…

使用網關和Spring Security進行認證和授權

個人名片 &#x1f393;作者簡介&#xff1a;java領域優質創作者 &#x1f310;個人主頁&#xff1a;碼農阿豪 &#x1f4de;工作室&#xff1a;新空間代碼工作室&#xff08;提供各種軟件服務&#xff09; &#x1f48c;個人郵箱&#xff1a;[2435024119qq.com] &#x1f4f1…

jquery發送jsonp請求

使用 jQuery 發送 JSONP 請求相對來說比較簡單&#xff0c;以下是示例代碼&#xff1a; $.ajax({url: "http://example.com/data",dataType: "jsonp",jsonp: "callback",jsonpCallback: "myCallback" }).done(function(response) {//…

Linux命令更新-sort 和 uniq 命令

簡介 sort 和 uniq 都是 Linux 系統中常用的文本處理命令。 sort 命令用于對文件內容進行排序。 uniq 命令用于去除文件中重復出現的行。 1. sort 命令 命令格式 sort [選項] [文件]選項&#xff1a; -n: 按照數字進行排序 -r: 反向排序 -c: 統計每個元素出現的次數 -…

怎么錄制視頻?電腦錄制,試試這3種方法

在數字化快速發展的時代&#xff0c;視頻已經成為我們傳遞信息、分享生活、表達情感的重要載體。每一個人都希望自己能夠掌握視頻錄制技巧&#xff0c;輕松駕馭影像的力量&#xff0c;創造出屬于自己的視覺盛宴。 那么&#xff0c;怎么錄制視頻呢&#xff1f;首先選擇一款好用…

vue腳手架配置代理請求

在 Vue 腳手架中&#xff0c;可以通過配置vue.config.js文件來設置代理請求&#xff0c;以解決跨域問題或實現其他代理需求。以下是兩種常見的配置方式&#xff1a; 方法一&#xff1a; 在vue.config.js中添加如下配置&#xff1a; module.exports {devServer: {proxy: http…

《信息與電腦(理論版)》是什么級別的期刊?是正規期刊嗎?能評職稱嗎?

問題解答 問&#xff1a;《信息與電腦(理論版)》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知網收錄的正規學術期刊。 問&#xff1a;《信息與電腦(理論版)》級別&#xff1f; 答&#xff1a;省級。主管單位&#xff1a;北京電子控股有限責任公司 主辦…