一、線程概述
線程(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-hant/n/205875.html