一、線程的概念
線程是操作系統調度的最小單位,它是進程中的一個執行單位。一個進程可以擁有多個線程,這些線程可以共享進程的資源,包括內存、文件等。線程之間的切換比進程之間的切換代價要小很多,也更加高效。在Linux系統中,線程的實現依賴於操作系統提供的POSIX線程庫(pthread)。
二、線程的創建和銷毀
線程的創建和銷毀是多線程編程的基本操作。在Linux系統中,線程的創建和銷毀都是通過pthread庫提供的函數實現的。例如,創建一個線程可以使用pthread_create函數,銷毀一個線程可以使用pthread_cancel函數。
void *thread_func(void *arg){ printf("This is a pthread.\n"); pthread_exit(NULL); } int main(){ pthread_t tid; int ret = pthread_create(&tid, NULL, thread_func, NULL); //創建一個線程 if(ret){ printf("Create pthread error!\n"); return -1; } pthread_join(tid, NULL); //等待子線程結束 return 0; }
在上面的示例代碼中,pthread_t類型的tid變數儲存著新建線程的線程ID。pthread_create函數接受四個參數,第一個參數是指向新線程標識符的指針,第二個參數用於設置線程屬性,第三個參數是新線程運行的函數,第四個參數是傳給函數的參數。pthread_join函數用於等待子線程結束。
三、線程同步與互斥
線程同步與互斥是多線程編程中必須掌握的概念,它們是保證多個線程安全共享數據的重要手段。Linux系統提供了多種同步和互斥機制,其中最常用的是互斥鎖和條件變數。
pthread_mutex_t mutex; pthread_cond_t cond; void *thread_func(void *arg){ // 模擬線程同步 pthread_mutex_lock(&mutex); // 加鎖 pthread_cond_wait(&cond, &mutex); // 等待條件變數的信號 pthread_mutex_unlock(&mutex); // 解鎖 printf("Thread is over.\n"); pthread_exit(NULL); } int main(){ pthread_t tid; pthread_mutex_init(&mutex, NULL); // 初始化互斥鎖 pthread_cond_init(&cond, NULL); // 初始化條件變數 int ret = pthread_create(&tid, NULL, thread_func, NULL); // 創建一個線程 if(ret){ printf("Create pthread error!\n"); return -1; } // 模擬線程同步 sleep(5); pthread_cond_signal(&cond); // 發送信號 pthread_join(tid, NULL); // 等待子線程結束 pthread_mutex_destroy(&mutex); // 銷毀互斥鎖 pthread_cond_destroy(&cond); // 銷毀條件變數 return 0; }
在上面的示例代碼中,使用pthread_mutex_t定義了互斥鎖和pthread_cond_t定義了條件變數。pthread_mutex_lock和pthread_mutex_unlock函數用於加鎖和解鎖互斥鎖,pthread_cond_wait函數用於等待條件變數的信號,pthread_cond_signal函數用於發送信號。
四、線程池
線程池是提高多線程執行效率的重要手段,它可以使得多個線程共享一定數量的線程資源,避免了線程頻繁創建和銷毀的開銷。在Linux系統中,線程池的實現主要依賴於pthread庫提供的線程創建、銷毀和管理函數。
#define THREAD_NUM 5 #define QUEUE_SIZE 10 pthread_t threads[THREAD_NUM]; int queue[QUEUE_SIZE]; int front = 0, rear = 0; pthread_mutex_t mutex; pthread_cond_t cond; void *worker_func(void *arg){ int thread_id = *(int *)arg; while(1){ pthread_mutex_lock(&mutex); // 加鎖 while(front == rear){ // 隊列為空,等待信號 pthread_cond_wait(&cond, &mutex); } int task = queue[front++]; // 從隊列中取出任務 printf("Thread %d get task %d.\n", thread_id, task); pthread_mutex_unlock(&mutex); // 解鎖 sleep(2); // 模擬任務執行 } pthread_exit(NULL); } int main(){ pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); int tids[THREAD_NUM]; for(int i = 0; i < THREAD_NUM; i++){ tids[i] = i + 1; pthread_create(&threads[i], NULL, worker_func, &tids[i]); // 創建線程 } srand(time(NULL)); for(int i = 0; i < 20; i++){ // 向隊列中添加任務 pthread_mutex_lock(&mutex); // 加鎖 while((rear + 1) % QUEUE_SIZE == front){ // 隊列已滿,等待信號 pthread_cond_wait(&cond, &mutex); } queue[rear] = rand() % 100; // 添加任務 rear = (rear + 1) % QUEUE_SIZE; printf("Task %d added to queue.\n", i); pthread_mutex_unlock(&mutex); // 解鎖 pthread_cond_signal(&cond); // 發送信號 sleep(1); } for(int i = 0; i < THREAD_NUM; i++){ pthread_cancel(threads[i]); // 結束線程 } pthread_mutex_destroy(&mutex); // 銷毀互斥鎖 pthread_cond_destroy(&cond); // 銷毀條件變數 return 0; }
在上面的示例代碼中,創建了一個固定大小的隊列來儲存任務,使用互斥鎖保證隊列的線程安全,使用條件變數通信。線程池中包括多個工作線程,它們都從隊列中獲取任務進行執行。主線程向隊列中添加任務,使用pthread_cond_broadcast函數給所有線程發送信號,線程池的核心在於阻塞等待隊列消息,並動態創建線程。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/249916.html