Linux探秘坊-------15.線程概念與控制

1.線程概念

1.什么是線程

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

2.線程 vs 進程

在這里插入圖片描述
不同的操作系統有不同的實現方式:

  • linux :直接使用pcb的功能來模擬線程,不創建新的數據結構
  • windows: 使用新的數據結構TCB,來進行實現,一個PCB里有很多個TCB

3.資源劃分

詳情可見操作系統書籍中的存儲器管理虛擬存儲器管理章節!!!!

4.線程理解

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

2.線程和進程的區別

在這里插入圖片描述

  • 黃字代表線程特有的私有數據
  • 一組寄存器和上下文數據---------------證明線程是可以被獨立調用
  • 棧--------------證明線程是動態的

1.進程的線程共享!!!!!!!!!!

同?地址空間,因此 Text Segment 、 Data Segment 都是共享的,如果定義?個函數,在各線程中都可以調? ,如果定義?個全局變量,在各線程中都可以訪問到, 除此之外,各線程還共享以下進程資源和環境:

  • ?件描述符表 (fd)
  • 每種信號的處理?式(SIG_IGN、SIG_DFL或者?定義的信號處理函數)
  • 當前?作?錄
  • ??id和組id

1.父子進程只有代碼段是共享的,但主線程和子線程連地址空間都是共享的,所以他們可以使用共享的函數和全局變量 意思就是如果子線程的全局變量被修改了,主線程看到的是同一個全局變量,也會變化 輕松實現類似進程間通信!!!!!!!
2.而全局變量在父子進程中是寫實拷貝,子變父不變 !!!!!!!!!

在這里插入圖片描述

3.linux的線程控制

1.線程創建

創建函數:
在這里插入圖片描述
運行后使用 ps - aL指令查看線程
在這里插入圖片描述

2.pthread庫的引入----為什么需要有線程庫?

在這里插入圖片描述

4.pthread庫的使用

  • 與線程有關的函數構成了?個完整的系列,絕?多數函數的名字都是“pthread_”打頭的
    ? 要使?這些函數庫,要通過引?頭?件 <pthread.h>
    ? 鏈接這些線程函數庫時要使?編譯器命令的“-lpthread”選項

1.線程創建—pthread_create()

在這里插入圖片描述

  • thread是新線程的標識符,是輸出型參數(讓主線程獲取,便于調用其他函數)

2.線程等待—pthread_join()

在這里插入圖片描述

  • 這里retval拿到的是子線程的退出碼,即子線程函數的返回值,但返回值是void *
  • 所以retval的類型應當是void* 的地址類型即void**

在這里插入圖片描述

  • 其中,routine是子線程的入口函數,routine函數結束的話子線程也就結束了

3.線程取消或終止—pthread_exit()/pthread_cancel()

1-----------------pthread_exit()
在這里插入圖片描述
2-----------------pthread_cancel()

在這里插入圖片描述

  • 如果線程被主線程或其他線程取消,那么主線程join函數得到的返回值固定為-1

4.線程分離—int pthread_detach(pthread_t thread);

在這里插入圖片描述

5.線程ID及進程地址空間布局

1.--------------------------pthread_self函數獲取id
在這里插入圖片描述
2.--------------------------pthread庫的動態鏈接
在這里插入圖片描述

  • 所有的線程都是在thread庫中建立的,線程的管理塊都存儲在庫中具體的pcb由用戶使用系統調用在內核中建立

在這里插入圖片描述

  • 創建線程的具體圖例

在這里插入圖片描述

6.線程互斥

來看一個買票的例子:

/ 操作共享變量會有問題的售票系統代碼
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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, (void*)"thread 1");pthread_create(&t2, NULL, route, (void*)"thread 2");pthread_create(&t3, NULL, route, (void*)"thread 3");pthread_create(&t4, NULL, route, (void*)"thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);
}

在這里插入圖片描述

  • 為了避免買票變成負數,所以要使用 來保證線程間的互斥

為什么會變成負數??????

  • 因為ticket–操作并不是原子的----------即無法一步完成------要先把ticket大小傳入cpu,再在cpu中進行運算,最后再寫回ticket全局變量中--------一共有三步
  • 可能某一個線程計算完后ticket為0,但還沒寫回ticket,另一個線程就又開始運行,這個時候ticket是1,還能通過if條件語句,最后兩個線程都執行ticket–,全部寫回后,ticket變成了-1!!!!

在這里插入圖片描述

1.鎖的使用

#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int ticket = 100;
pthread_mutex_t mutex;//設置鎖----這里是全局鎖,用完后會自動銷毀
void* route(void* arg) 
{char* id = (char*)arg;while (1) {pthread_mutex_lock(&mutex);//pthread_mutex_lock--------上鎖if (ticket > 0) {usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;pthread_mutex_unlock(&mutex);// pthread_mutex_unlock--------解鎖} else {pthread_mutex_unlock(&mutex);// pthread_mutex_unlock--------解鎖break;}}return nullptr;
}
int main(void) {pthread_t t1, t2, t3, t4;pthread_mutex_init(&mutex, NULL);// pthread_mutex_init------初始化鎖pthread_create(&t1, NULL, route, (void*)"thread 1");pthread_create(&t2, NULL, route, (void*)"thread 2");pthread_create(&t3, NULL, route, (void*)"thread 3");pthread_create(&t4, NULL, route, (void*)"thread 4");pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_join(t4, NULL);pthread_mutex_destroy(&mutex);//pthread_mutex_destroy-------刪除鎖
}

pthread 庫是 POSIX 線程庫,提供了多線程編程的 API,其中包括用于線程同步的鎖機制。以下是 pthread 中常見的鎖函數及其解釋:


1. 互斥鎖(Mutex)

互斥鎖用于保護臨界區,確保同一時間只有一個線程可以訪問共享資源。

相關函數:
  • pthread_mutex_init
    初始化互斥鎖。

    int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
    
    • mutex:指向互斥鎖對象的指針。
    • attr:屬性對象(通常設為 NULL 使用默認屬性)。
    • 成功返回 0,失敗返回錯誤碼。
  • pthread_mutex_lock
    加鎖。如果鎖已被其他線程持有,則調用線程阻塞直到鎖被釋放。

    int pthread_mutex_lock(pthread_mutex_t *mutex);
    
  • pthread_mutex_trylock
    嘗試加鎖,如果鎖已被持有則立即返回錯誤(非阻塞)。

    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    
    • 成功返回 0,鎖被持有時返回 EBUSY
  • pthread_mutex_unlock
    解鎖。

    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    
  • pthread_mutex_destroy
    銷毀互斥鎖,釋放資源。

    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    

7.線程同步

在這里插入圖片描述

1.條件變量函數介紹

-------------------為了避免加鎖后導致線程饑餓而設置的變量

條件變量用于線程間通信,通常與互斥鎖配合使用,實現線程的等待和喚醒機制。

相關函數:
  • pthread_cond_init //第二個變量基本是設置為nullptr
    初始化條件變量。

    int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
    
  • pthread_cond_wait // 第二個參數是上文的互斥鎖
    等待條件變量,并釋放關聯的互斥鎖(原子操作)。

    int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
    
  • pthread_cond_signal
    喚醒一個等待該條件變量的線程。

    int pthread_cond_signal(pthread_cond_t *cond);
    
  • pthread_cond_broadcast
    喚醒所有等待該條件變量的線程。

    int pthread_cond_broadcast(pthread_cond_t *cond);
    
  • pthread_cond_destroy
    銷毀條件變量。

    int pthread_cond_destroy(pthread_cond_t *cond);
    
#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <pthread.h>#define NUM 5
int cnt = 1000;pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER; // 定義鎖
pthread_cond_t gcond = PTHREAD_COND_INITIALIZER;   // 定義條件變量// 等待是需要等,什么條件才會等呢?票數為0,等待之前,就要對資源的數量進行判定。
// 判定本身就是訪問臨界資源!,判斷一定是在臨界區內部的.
// 判定結果,也一定在臨界資源內部。所以,條件不滿足要休眠,一定是在臨界區內休眠的!
// 證明一件事情:條件變量,可以允許線程等待
// 可以允許一個線程喚醒在cond等待的其他線程, 實現同步過程
void *threadrun(void *args)
{std::string name = static_cast<const char *>(args);while (true){pthread_mutex_lock(&glock);// 直接讓對用的線程進行等待?? 臨界資源不滿足導致我們等待的!pthread_cond_wait(&gcond, &glock); // glock在pthread_cond_wait之前,會被自動釋放掉std::cout << name << " 計算: " << cnt << std::endl;cnt++;pthread_mutex_unlock(&glock);}
}int main()
{std::vector<pthread_t> threads;for (int i = 0; i < NUM; i++){pthread_t tid;char *name = new char[64];snprintf(name, 64, "thread-%d", i);//snprintf函數往name中打印字符串int n = pthread_create(&tid, nullptr, threadrun, name);if (n != 0)continue;threads.push_back(tid);sleep(1);}sleep(3);// 每隔1s喚醒一個線程while(true){std::cout << "喚醒所有線程... " << std::endl;pthread_cond_broadcast(&gcond);// std::cout << "喚醒一個線程... " << std::endl;// pthread_cond_signal(&gcond);sleep(1);}for (auto &id : threads){int m = pthread_join(id, nullptr);(void)m;}return 0;
}

在這里插入圖片描述
在這里插入圖片描述

8.生產者消費者模型

在這里插入圖片描述
在這里插入圖片描述

  • 生產者和消費者之間要有順序地進行工作,所以是同步的
基于阻塞隊列實現生產者消費者模型:

----------------什么是阻塞隊列?

在這里插入圖片描述

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

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

相關文章

Github庫鏡像到本地私有Gitlab服務器

上一節我們看了如何架設自己的Gitlab服務器&#xff0c;今天我們看怎么把Github庫轉移到自己的Gitlab上。 首先登錄github&#xff0c;進入自己的庫復制地址。 克隆鏡像庫 在本地新建一個文件夾 在文件夾執行CMD指令 git clone --mirror gitgithub.com:thinbug/A.git–mirror參…

【C++】——類和對象(中)——默認成員函數

一、類的默認成員函數默認成員函數就是用戶沒有顯示實現&#xff0c;不過編譯器會自動生成的成員函數&#xff0c;稱為默認成員函數。一個類默認成員函數一共有6個&#xff0c;在我們不寫的情況下&#xff0c;編譯器就會自動生成這6個成員函數&#xff0c;不過我們重點要學習的…

MATLAB知識點總結

1.將A圖與B圖相同范圍內歸一化顯示在同一個figure上&#xff1a; figure, plot(A(150:450,500)/max(A(150:450,500))) hold on plot(D(150:450,500)/max(D(150:450,500)),‘R’) 將兩幅圖像的一定范圍顯示在同一圖像上。 figure,plot(A(350,100:450)) hold on plot(G(350,100:4…

易天光通信10G SFP+ 1550nm 120KM 雙纖光模塊:遠距離傳輸的實力擔當

目錄 前言 一、10G SFP雙纖光模塊概述 二、易天10G SFP 120KM 雙纖光模塊核心優勢與應用 核心優勢&#xff1a; 主要關鍵應用如下&#xff1a; 三、易天10G SFP 120KM 雙纖光模塊客戶優勢 總結 關于易天 前言 在構建高效穩定的網絡架構時&#xff0c;10G SFP 光模塊 12…

【深度學習】神經網絡 批量標準化-part6

九、批量標準化是一種廣泛使用的神經網絡正則化技術&#xff0c;對每一層的輸入進行標準化&#xff0c;進行縮放和平移&#xff0c;目的是加速訓練&#xff0c;提高模型穩定性和泛化能力&#xff0c;通常在全連接層或是卷積層之和&#xff0c;激活函數之前使用核心思想對每一批…

【數據可視化-67】基于pyecharts的航空安全深度剖析:墜毀航班數據集可視化分析

&#x1f9d1; 博主簡介&#xff1a;曾任某智慧城市類企業算法總監&#xff0c;目前在美國市場的物流公司從事高級算法工程師一職&#xff0c;深耕人工智能領域&#xff0c;精通python數據挖掘、可視化、機器學習等&#xff0c;發表過AI相關的專利并多次在AI類比賽中獲獎。CSDN…

【科研繪圖系列】R語言繪制分組箱線圖

文章目錄 介紹 加載R包 數據下載 導入數據 畫圖1 畫圖2 合并圖 系統信息 參考 介紹 【科研繪圖系列】R語言繪制分組箱線圖 加載R包 library(ggplot2) library(patchwork)rm(list = ls()) options(stringsAsFactors = F)

基于Android的旅游計劃App

項目介紹系統打開進入登錄頁面&#xff0c;如果沒有注冊過賬號&#xff0c;點擊注冊按鈕輸入賬號、密碼、郵箱即可注冊&#xff0c;注冊后可登錄進入系統&#xff0c;系統分為首頁、預訂、我的三大模塊&#xff0c;下面具體詳細說說三大模塊功能說明。1.首頁顯示旅游備忘或旅游…

【LeetCode 2163. 刪除元素后和的最小差值】解析

目錄LeetCode中國站原文原始題目題目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a;講解分割線的藝術&#xff1a;前后綴分解與優先隊列的完美邂逅第一部分&#xff1a;算法思想 —— “分割線”與前后綴分解1. 想象一條看不見的“分割線”2. 前后綴分解&#xff1…

控制鼠標和鍵盤

控制鼠標和鍵盤的Python庫Python中有多個庫可以用于控制鼠標和鍵盤&#xff0c;常用的包括pyautogui、pynput、keyboard和mouse等。這些庫提供了模擬用戶輸入的功能&#xff0c;適用于自動化測試、GUI操作等場景。使用pyautogui控制鼠標pyautogui是一個跨平臺的庫&#xff0c;支…

基于按鍵開源MultiButton框架深入理解代碼框架(二)(指針的深入理解與應用)

文章目錄2、針對該開源框架理解3、分析代碼3.1 再談指針、數組、數組指針3.2 繼續分析源碼2、針對該開源框架理解 在編寫按鍵模塊的框架中&#xff0c;一定要先梳理按鍵相關的結構體、枚舉等變量。這些數據是判斷按鍵按下、狀態跳轉、以及綁定按鍵事件的核心。 這一部分定義是…

web前端渡一大師課 CSS屬性計算過程

你是否了解CSS 的屬性計算過程呢? <body> <h1>這是一個h1標題</h1> </body> 目前我們沒有設置改h1的任何樣式,但是卻能看到改h1有一定的默認樣式,例如有默認的字體大小,默認的顏色 那么問題來了,我們這個h1元素上面除了有默認字體大小,默認顏色等…

Redis高頻面試題:利用I/O多路復用實現高并發

Redis 通過 I/O 多路復用&#xff08;I/O Multiplexing&#xff09;技術實現高并發&#xff0c;這是其單線程模型能夠高效處理大量客戶端連接的關鍵。以下是通俗易懂的解釋&#xff0c;結合 Redis 的工作原理&#xff0c;詳細說明其實現過程。 1. 什么是 I/O 多路復用&#xff…

爬蟲小知識(二)網頁進行交互

一、提交信息到網頁 1、模塊核心邏輯 “提交信息到網頁” 是網絡交互關鍵環節&#xff0c;借助 requests 庫的 post() 函數&#xff0c;能模擬瀏覽器向網頁發數據&#xff08;如表單、文件 &#xff09;&#xff0c;實現信息上傳&#xff0c;讓我們能與網頁背后的服務器 “溝通…

WPF學習(五)

文章目錄一、FileStream和StreamWriter理解1.1、具體關系解析1.2、類比理解1.3、總結1.4、示例代碼1.5、 WriteLine()和 Write&#xff08;&#xff09;的區別1.6、 StreamWriter.Close的作用二、一、FileStream和StreamWriter理解 在 C# 中&#xff0c;StreamWriter 和 FileS…

ctf.show-web習題-web2-最簡單的sql注入-flag獲取詳解、總結

解題思路打開靶場既然提示是最簡單的sql注入了&#xff0c;那么直接嘗試永真登錄1 or 11#這里閉合就是簡單的單引號可以看到沒登錄成功&#xff0c;但是有回顯&#xff1a;歡迎你&#xff0c;ctfshowsql注入最喜歡的就是回顯了&#xff01;這題的思路就是靠這個回顯&#xff0c…

upload-labs 靶場通關(1-20)

目錄 Pass-01(JS 繞過) Pass-02(文件類型驗證) Pass-03(黑名單驗證) Pass-04(黑名單驗證.htaccess) Pass-05(大小寫繞過) Pass-06(末尾空格) Pass-07(增加一個.) Pass-08(增加一個::$DATA) Pass-09&#xff08;代碼不嚴謹&#xff09; Pass-10&#xff08;PPHPHP&am…

[附源碼+數據庫+畢業論文]基于Spring+MyBatis+MySQL+Maven+vue實現的酒店預訂管理系統,推薦!

摘 要 使用舊方法對酒店預訂信息進行系統化管理已經不再讓人們信賴了&#xff0c;把現在的網絡信息技術運用在酒店預訂信息的管理上面可以解決許多信息管理上面的難題&#xff0c;比如處理數據時間很長&#xff0c;數據存在錯誤不能及時糾正等問題。 這次開發的酒店預訂管理系…

LSTM入門案例(時間序列預測)| pytorch實現(可復現)

需求 假如我有一個時間序列&#xff0c;例如是前113天的價格數據&#xff08;訓練集&#xff09;&#xff0c;然后我希望借此預測后30天的數據&#xff08;測試集&#xff09;&#xff0c;實際上這143天的價格數據都已經有了。這里為了簡單&#xff0c;每一天的數據只有一個價…

Axure RP 10 預覽顯示“無標題文檔”的空白問題探索【護航版】

1. 安裝情況 官網 Axure RP 10&#xff1a;Download Axure RP 10 - Axure &#xff08;PS&#xff1a;11都出了&#xff09; 版本&#xff1a;10.0.0.3924 激活碼&#xff1a;49bb9513c40444b9bcc3ce49a7a022f9 &#xff08;10/11都可以用&#xff0c;但只嘗試了10&#xff…