linux----------------------線程同步與互斥(上)

1.線程互斥

1-1 進程線程間的互斥相關背景概念

臨界資源:多線程執行流共享的資源就叫做臨界資源

臨界區:每個線程內部訪問臨界資源的代碼就叫做臨界區

互斥:任何時刻,互斥保證只有一個執行進入臨界區,對臨界資源起到保護作用

原子性:不會被任何調度打斷的操作,只有兩種狀態一個是完成一個是未完成

1-2互斥量mutex

大部分情況線程使用的數據都是局部變量,變量的地址存放在線程棧空間里面,這種情況,變量歸屬單個線程,其他線程無法獲得該變量。有的時候多個線程需要對同一個變量進行操作找個變量稱為共享變量,多個線程并發的操作共享變量會帶來一些問題

// 操作共享變量會有問題的售票系統代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 100;void *route(void *arg)
{
char *id = (char*)arg;
while ( 1 ) {
if ( ticket > 0 ) {
usleep(1000);
printf("%s sells ticket:%d\n", id, ticket);
ticket--;} 
else {break;}
}
}
int main( void )
{pthread_t t1, t2, t3, t4;pthread_create(&t1, NULL, route, "thread 1");pthread_create(&t2, NULL, route, "thread 2");pthread_create(&t3, NULL, route, "thread 3");pthread_create(&t4, NULL, route, "thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);
}
?次執?結果:
thread 4 sells ticket:100
...
thread 4 sells ticket:1
thread 2 sells ticket:0
thread 1 sells ticket:-1
thread 3 sells ticket:-2

為什么只有100張票到0了的時候還有票能售出去呢?

這就是線程并發執行處理共享數據帶來的問題,在我處理最后一張票的時候其他線程也進來了他們看到的都是1此時他們還不知道這個票已經被其他線程給執行完了。如何解決這個問題呢?

代碼必須要有互斥行為:當代碼進入臨界區執行時不允許其他線程進入臨界區

如果多個線程同時要求執?臨界區的代碼,并且臨界區沒有線程在執?,那么只能允許?個線程
進?該臨界區。
如果線程不在臨界區中執?,那么該線程不能阻?其他線程進?臨界區。
要做到這三點只需要在臨界區資源上一把鎖。linux上提供的這把鎖就叫做互斥量

互斥量的接口

初始化互斥量有兩種第

1 靜態分配

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
2 動態分配
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const
pthread_mutexattr_t *restrict attr);
參數:
mutex:要初始化的互斥量
attrNULL
銷毀互斥量
銷毀互斥量需要注意
使? PTHREAD_ MUTEX_ INITIALIZER 初始化的互斥量不需要銷毀
不要銷毀?個已經加鎖的互斥量
已經銷毀的互斥量,要確保后?不會有線程再嘗試加鎖
int pthread_mutex_destroy(pthread_mutex_t *mutex);

互斥量加鎖和解鎖

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
返回值:成功返回0,失敗返回錯誤號

調用 pthread_lock是,可能會遇到以下情況

互斥量處于未上鎖狀態,該函數會講把互斥量鎖定返回成功

如何發起函數調用時,其他線程已鎖定互斥量,沒有競爭到互斥量資源,此時pthread_lock調用會陷入阻塞,直到互斥量解鎖

修該上面的售票代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
int ticket = 100;
pthread_mutex_t mutex;
void *route(void *arg)
{
char *id = (char*)arg;
while ( 1 ) {
pthread_mutex_lock(&mutex);if ( ticket > 0 ) {
usleep(1000);
printf("%s sells ticket:%d\n", id, ticket);
ticket--;
pthread_mutex_unlock(&mutex);
// sched_yield(); 放棄CPU
} 
else {
pthread_mutex_unlock(&mutex);
break;
}}}int main( void )
{
pthread_t t1, t2, t3, t4;
pthread_mutex_init(&mutex, NULL);
pthread_create(&t1, NULL, route, "thread 1");
pthread_create(&t2, NULL, route, "thread 2");
pthread_create(&t3, NULL, route, "thread 3");
pthread_create(&t4, NULL, route, "thread 4");
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
pthread_mutex_destroy(&mutex);
}

1-3 互斥量的封裝

test_4_22_httpserve/Mutex.h · liu xi peng/linux---ubuntu系統 - 碼云 - 開源中國

大家有興趣的可以點進去看一下

2.線程同步

2-1 條件變量

當一個線程互斥地訪問某個變量時,他可能發現在其他線程狀態改變之前他什么也做不了

例如?個線程訪問隊列時,發現隊列為空,它只能等待,只到其它線程將?個節點添加到隊列

中。這種情況就需要?到條件變量。

2-2 同步概念與競態條件

同步:在保證數據安全的前提下,讓線程能夠按照某種特定的順序訪問臨界資源,從?有效避免
饑餓問題,叫做同步
競態條件:因為時序問題,?導致程序異常,我們稱之為競態條件。在線程場景下,這種問題也
不難理解

2-3 條件變量函數

初始化

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t
*restrict attr);
參數:
cond:要初始化的條件變量
attrNULL
銷毀
1 int pthread_cond_destroy(pthread_cond_t *cond)
等待條件滿?
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict
mutex);
參數:
cond:要在這個條件變量上等待
mutex:互斥量,后?詳細解釋
喚醒等待
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *active( void *arg )
{
std::string name = static_cast<const char*>(arg);
while (true){
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
std::cout << name << " 活動..." << std::endl;
pthread_mutex_unlock(&mutex);
}
}
int main( void )
{
pthread_t t1, t2;
pthread_create(&t1, NULL, active, (void*)"thread-1");
pthread_create(&t2, NULL, active, (void*)"thread-2");
sleep(3); // 可有可?,這?確保兩個線程已經在運?
while(true)
{
// 對?測試
// pthread_cond_signal(&cond); // 喚醒?個線程
pthread_cond_broadcast(&cond); // 喚醒所有線程
sleep(1);
}pthread_join(t1, NULL);
pthread_join(t2, NULL);
}

運行結果:

thread-1 活動...
thread-2 活動...
thread-1 活動...
thread-1 活動...
thread-2 活動...
2-4 ?產者消費者模型
321原則(便于記憶)
產消費模型是一種多線程并發的生產模型他有三種關系分別是消費者對消費者,生產者對生產者,消費著對生產者,分別是互斥,互斥,互斥和同步關系
由線程來承擔消費者和生產者,線程可有多個,通常有一個特定的數據結構提供的緩沖區這個緩存區通常被成為交易場所

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

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

相關文章

百度AI的開放新篇章:文心4.5本地化部署指南與未來生態戰略展望

百度AI的開放新篇章&#xff1a;文心4.5本地化部署指南與未來生態戰略展望 一起來玩轉文心大模型吧&#x1f449;文心大模型免費下載地址&#xff1a;https://ai.gitcode.com/theme/1939325484087291906 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30…

筆記/sklearn中的數據劃分方法

文章目錄一、前言二、數據劃分方法1. 留出法&#xff08;Hold-out&#xff09;2. K折交叉驗證&#xff08;K-Fold&#xff09;3. 留一法&#xff08;Leave-One-Out&#xff09;三、總結一、前言 簡要介紹數據劃分在機器學習中的作用。 二、數據劃分方法 1. 留出法&#xff0…

Android14 開屏頁SplashScreen設置icon圓角的原理

簡介 我們在看到一個應用在啟動的時候會看到一個啟動的icon,這個圖標是應用的icon當然也是可以應用自己去控制的如 <item name="android:windowSplashScreenAnimatedIcon">@drawable/adas_icon</item> 圖上的效果明顯不理想,圖標是自帶圓角,而且還是…

flutter redux狀態管理

&#x1f4da; Flutter 狀態管理系列文章目錄 Flutter 狀態管理(setState、InheritedWidget、 Provider 、Riverpod、 BLoC / Cubit、 GetX 、MobX 、Redux) setState() 使用詳解&#xff1a;原理及注意事項 InheritedWidget 組件使用及原理 Flutter 中 Provider 的使用、注…

AMIS全棧低代碼開發

amis是百度開源的前端低代碼框架&#xff0c;它通過JSON配置來生成各種后臺頁面&#xff0c;旨在簡化前端開發過程&#xff0c;提高開發效率&#xff0c;降低開發門檻。以下是詳細介紹&#xff1a; 核心特點&#xff1a; 可視化開發&#xff1a;允許開發者通過可視化方式構建頁…

【Python基礎】變量、運算與內存管理全解析

一、刪除變量與垃圾回收&#xff1a;內存管理的底層邏輯 在Python中&#xff0c;變量是對象的引用&#xff0c;而不是對象本身。當我們不再需要某個變量時&#xff0c;可以用del語句刪除它的引用&#xff0c;讓垃圾回收機制&#xff08;GC&#xff09;自動清理無引用的對象。 1…

Spring Boot + Javacv-platform:解鎖音視頻處理的多元場景

Spring Boot Javacv-platform&#xff1a;解鎖音視頻處理的多元場景 一、引言 在當今數字化時代&#xff0c;音視頻處理已成為眾多應用場景中不可或缺的一部分&#xff0c;從在線教育、視頻會議到短視頻平臺、智能安防等&#xff0c;音視頻數據的處理與分析需求日益增長。Java…

k8s 的基本原理、架構圖、使用步驟和注意事項

Kubernetes&#xff08;k8s&#xff09;是一個開源的容器編排平臺&#xff0c;用于自動化部署、擴展和管理容器化應用。以下是其基本原理、使用步驟和注意事項的總結&#xff1a;一、k8s 基本原理核心架構 Master 節點&#xff1a;控制集群的核心組件&#xff0c;包括&#xff…

Qt 多線程編程:單例任務隊列的設計與實現

引言&#xff1a; 在現代應用程序開發中&#xff0c;多線程編程已成為處理異步任務的標配。對于 GUI 應用而言&#xff0c;保持主線程的響應性尤為重要。本文將詳細介紹一個基于 Qt 的單例任務隊列實現方案&#xff0c;它通過線程池和單例模式&#xff0c;優雅地解決了后臺任務…

OpenEuler操作系統中檢測插入的USB設備并自動掛載

OpenEuler操作系統中檢測插入的USB設備并自動掛載 項目需求&#xff1a;工控機上openeuler操作系統是無界面版本的&#xff0c;在工控機上連接了激光雷達&#xff0c;當激光雷達采集完數據&#xff0c;我們要將采集數據導入u盤&#xff0c;故需要在工控機上插入u盤&#xff0c;…

《Spring 中上下文傳遞的那些事兒》Part 11:上下文傳遞最佳實踐總結與架構演進方向

&#x1f4dd; Part 11&#xff1a;上下文傳遞最佳實踐總結與架構演進方向 經過前面幾篇文章的深入探討&#xff0c;我們已經系統性地學習了 Spring 應用中上下文傳遞的各種技術原理、常見問題以及解決方案。從 Web 請求上下文到異步任務、從多租戶隔離到日志脫敏&#xff0c;…

使用云虛擬機搭建hadoop集群環境

使用云虛擬機搭建hadoop集群環境 安裝jdk17 配置docker網絡 docker network create --subnet172.18.0.0/16 hadoop 172.18.0.0&#xff1a;這是子網的網絡地址&#xff0c;也就是這個網絡的起始地址。/16&#xff1a;這是子網掩碼&#xff08;Network Mask&#xff09;&#x…

【機器學習】吳恩達機器學習課程代碼作業-Python版本

吳恩達老師的機器學習課程作業是MATLAB版本&#xff08;Octave&#xff09;的&#xff0c;現在有點過時了&#xff0c;我參考了幾位大牛的代碼&#xff0c;將作業改成了Python3.6版本&#xff0c;并做了中文注釋&#xff0c;推薦使用Jupyter notebook。Python作業使用了原版數據…

2025年人工智能、虛擬現實與交互設計國際學術會議

重要信息 官網&#xff1a;www.aivrid.com 時間&#xff1a;2025年10月17-19日 地點&#xff1a;中國-東莞 部分介紹 征稿主題 包括但不限于&#xff1a; 生物特征 模式識別 機器視覺 專家系統 深度學習 智能搜索 自動編程 智能控制 智能機器…

SHA-256算法流程分析與詳解——Github工程結合示例和動畫演示

近日筆者在學習區塊鏈的相關知識&#xff0c;接觸到SHA-256算法&#xff0c;這里做一個知識梳理和總結。 強烈推薦大家自行去學習下面鏈接github上的工程&#xff0c;作者的動畫演示和解釋做的非常出色&#xff0c;邏輯非常清晰&#xff0c;B站搬運的對應的油管的講解視頻也放…

CSPNet: A New Backbone that can Enhance Learning Capability of CNN (CSP模塊)

3. Method 方法 3.1 Cross Stage Partial Network 跨階段局部網絡 3.1.1 Cross Stage Partial Network 跨階段局部網絡 3.1.1.1 ResNet 和 DenseNet 的優缺點主流的卷積神經網絡&#xff08;CNN&#xff09;架構&#xff0c;如ResNet [8]、ResNeXt [37]、DenseNet [11]&#x…

前端學習4:小白入門注冊表單的制作(包括詳細思考CSS、JS實現過程)

這篇我們來做一個簡單表單&#xff0c;即常見的注冊頁面吧~學習完這篇我們將學習到Input、label、CSS偽類、CSS入門、更多的JS操作等。。一、首先明確需求&#xff1a;直接模仿常見的注冊頁面&#xff0c;包括&#xff1a;用戶名、Email、性別&#xff08;單選按鈕男/女&#x…

強化學習 (RL) 新突破:超越游戲,走向復雜現實決策

強化學習 (RL) 新突破&#xff1a;超越游戲&#xff0c;走向復雜現實決策 強化學習&#xff08;Reinforcement Learning&#xff0c; RL&#xff09;作為人工智能的核心范式之一&#xff0c;歷經數十年的發展&#xff0c;正迎來一場深刻的范式轉移。曾以戰勝人類頂尖選手的Alph…

2025年6-7月AI領域關鍵進展:從藥物研發到全球監管--AI深度融入產業與社會

2025年6月至7月&#xff0c;人工智能領域繼續以驚人速度發展&#xff0c;在技術突破、行業應用、政策法規、企業戰略及學術研究等方面取得了一系列重要里程碑。以下為關鍵動態&#xff1a;一、技術突破&#xff1a; AI向生命科學和認知科學縱深挺進DeepMind啟動AI設計藥物人體試…

【TOOL】ubuntu升級cmake版本

文章目錄一、下載cmake腳本二、安裝一、下載cmake腳本 在編譯新工程時遇到cmake版本過低的情況&#xff0c;到 cmake官網 下載指定cmake安裝腳本&#xff1a; 若需下載指定版本&#xff0c;見上圖右上角藍框。 二、安裝 # 賦予可執行權限 sudo chmod x cmake-3.31.8-linux-x8…