Linux線程詳解

一、線程概述

線程(Thread)是程序執行流的最小單位,它是進程內的一個執行單元。一個進程可以有多個線程,每個線程都可以運行在單獨的CPU上。與進程不同,線程共享進程內的一些資源,如內存、文件等。

線程的創建和銷毀比進程要方便快捷,因為它們不需要分配獨立的地址空間。因此,線程適合於需要高並發的場景,在網路編程、多媒體應用、資料庫等應用中都有非常廣泛的應用。

二、線程的創建

在Linux下,線程是通過調用pthread_create函數創建的。該函數的原型如下:

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);

其中,thread 是指向pthread_t類型的指針,是線程的標識符,用於啟動、暫停、恢復和刪除線程;attr 是指向 pthread_attr_t 類型的指針,用於設置線程屬性,默認可以傳 NULL;start_routine 是指向函數的指針,這個函數是線程運行的起點;arg 是傳遞給線程的參數,可以是單個變數、結構體或指針。

下面的代碼演示了一個簡單的線程創建過程:

#include <stdio.h>
#include <pthread.h>

void *thread_func(void *arg) { 
    printf("Thread running\n");
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, thread_func, NULL);
    pthread_join(thread, NULL);
    return 0;
}

在這個例子中,線程運行的起點是 thread_func 函數,在該函數內部列印字元串 “Thread running”。在主函數中,調用 pthread_create 創建線程並傳入 thread_func 函數,等待線程執行完成後,調用 pthread_join 函數進行回收。

三、線程同步

在多線程環境下,由於多個線程可以同時訪問共享資源,因此需要同步操作以避免衝突。

Linux提供了多種同步機制,下面介紹其中兩種:互斥鎖和條件變數。

互斥鎖

互斥鎖(mutex)可以用來保證共享資源的互斥訪問。當一個線程獲取了互斥鎖,其他線程需要等待它釋放鎖後才能執行相應的操作。Linux下的互斥鎖實現在pthread.h頭文件中,它的主要函數包括:

  • pthread_mutex_init 初始化互斥鎖
  • pthread_mutex_destroy 銷毀互斥鎖
  • pthread_mutex_lock 獲取互斥鎖
  • pthread_mutex_unlock 釋放互斥鎖

下面是一個使用互斥鎖進行同步的例子:

#include <pthread.h>
#include <stdio.h>

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;

void *thread_func(void *arg) { 
    pthread_mutex_lock(&lock);
    counter++;
    printf("Thread ID: %d incremented counter to %d\n", (int)pthread_self(), counter);
    pthread_mutex_unlock(&lock);
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[10];
    for(int i = 0; i < 10; i++) {
        pthread_create(&threads[i], NULL, thread_func, NULL);
    }
    for(int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }
    printf("Final value of counter is %d\n", counter);
    return 0;
}

在這個例子中,10個線程共享變數counter,每個線程執行後將counter加1,並列印當前線程的ID和counter的值。由於多線程環境下,對共享變數的操作需要同步,因此在每個線程函數內部使用pthread_mutex_lock和pthread_mutex_unlock進行互斥訪問。

條件變數

條件變數(condition variable)是一種同步機制,它能夠使一個線程等待另一個線程的通知。線程在條件變數上等待,直到另一個線程使用pthread_cond_signal或pthread_cond_broadcast函數通知它可以繼續執行。Linux下的條件變數實現在pthread.h頭文件中,它的主要函數包括:

  • pthread_cond_init 初始化條件變數
  • pthread_cond_destroy 銷毀條件變數
  • pthread_cond_wait 等待條件變數
  • pthread_cond_signal 喚醒一個線程
  • pthread_cond_broadcast 喚醒所有線程

下面是一個使用條件變數進行同步的例子:

#include <pthread.h>
#include <stdio.h>

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int waiting = 1;

void *thread_func(void *arg) { 
    pthread_mutex_lock(&lock);
    while(waiting) {
        pthread_cond_wait(&cond, &lock);
    }
    printf("Thread ID: %d continuing...\n", (int)pthread_self());
    pthread_mutex_unlock(&lock);
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[5];
    for(int i = 0; i < 5; i++) {
        pthread_create(&threads[i], NULL, thread_func, NULL);
    }
    sleep(1);
    printf("Wake up threads ...\n");
    pthread_mutex_lock(&lock);
    waiting = 0;
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&lock);
    for(int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }
    return 0;
}

在這個例子中,5個線程在條件變數上等待,直到主線程調用pthread_cond_broadcast函數釋放條件變數並喚醒它們。線程運行的起點是thread_func函數,在該函數內部調用pthread_cond_wait等待條件變數,在條件變數被喚醒後,線程繼續執行並列印當前線程的ID。

四、線程的銷毀

在不需要某個線程繼續執行的時候,需要銷毀它以釋放內存等資源。Linux下,使用pthread_cancel函數可以向一個線程發送取消請求,這個請求是非同步執行的,即立即返回,線程本身仍然繼續執行。另外,還可以使用pthread_join函數等待線程執行完成後回收它的資源。

下面是一個使用pthread_cancel函數取消線程的例子:

#include <pthread.h>
#include <stdio.h>

void *thread_func(void *arg) { 
    int i = 0;
    while(1) {
        printf("Thread ID: %d count %d\n", (int)pthread_self(), i++);
    }
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, thread_func, NULL);
    sleep(3);
    pthread_cancel(thread);
    pthread_join(thread, NULL);
    printf("Thread canceled\n");
    return 0;
}

在這個例子中,創建了一個線程,不斷循環列印當前線程ID和計數器的值。在主程序中,通過調用pthread_cancel函數向線程發送取消請求,並使用pthread_join函數等待線程完成後回收資源。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/205875.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-07 17:47
下一篇 2024-12-07 17:47

相關推薦

  • Python線程等待指南

    本文將從多個方面詳細講解Python線程等待的相關知識。 一、等待線程結束 在多線程編程中,經常需要等待線程執行完畢再進行下一步操作。可以使用join()方法實現等待線程執行完畢再…

    編程 2025-04-29
  • Python兩個線程交替列印1到100

    這篇文章的主題是關於Python多線程的應用。我們將會通過實際的代碼,學習如何使用Python兩個線程交替列印1到100。 一、創建線程 在Python中,我們可以使用Thread…

    編程 2025-04-28
  • ROS線程發布消息異常解決方法

    針對ROS線程發布消息異常問題,我們可以從以下幾個方面進行分析和解決。 一、檢查ROS代碼是否正確 首先,我們需要檢查ROS代碼是否正確。可能會出現的問題包括: 是否正確初始化RO…

    編程 2025-04-28
  • Python線程池並發爬蟲

    Python線程池並發爬蟲是實現多線程爬取數據的常用技術之一,可以在一定程度上提高爬取效率和數據處理能力。本文將從多個方面對Python線程池並發爬蟲做詳細的闡述,包括線程池的實現…

    編程 2025-04-27
  • 如何在Linux中添加用戶並修改配置文件

    本文將從多個方面詳細介紹在Linux系統下如何添加新用戶並修改配置文件 一、添加新用戶 在Linux系統下創建新用戶非常簡單,只需使用adduser命令即可。使用以下命令添加新用戶…

    編程 2025-04-27
  • 如何解決linux jar包 invalid or corrupt jarfile問題

    對於許多開發人員和系統管理員在Linux環境下使用Java開發過程中遇到的一個常見的問題是 invalid or corrupt jarfile(無效或損壞的jar文件)錯誤。當您…

    編程 2025-04-27
  • 線程池中的一個線程異常了會被怎麼處理

    本文將從以下幾個方面對線程池中的一個線程異常了會被怎麼處理進行詳細闡述:異常的類型、如何捕獲異常、異常的處理方式。 一、異常的類型 在線程池中,可以出現多種類型的異常,例如線程執行…

    編程 2025-04-27
  • 在Linux上安裝JRE並配置環境變數

    本文將從以下幾個方面為您詳細闡述如何在Linux系統上,通過自己賬戶安裝JRE,並且配置環境變數。 一、安裝JRE 在進行安裝前,我們需要下載JRE的安裝包並解壓,可以從官方網站下…

    編程 2025-04-27
  • GTKAM:Linux下的照片管理器

    GTKAM是用於Linux操作系統的一款照片管理器,它支持多種相機及存儲設備,並提供了一系列強大的工具,讓用戶可以方便地瀏覽、管理、編輯和導出照片。本文將從多個方面對GTKAM進行…

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25

發表回復

登錄後才能評論