一、線程的概念
線程是操作系統調度的最小單位,它是進程中的一個執行單位。一個進程可以擁有多個線程,這些線程可以共享進程的資源,包括內存、文件等。線程之間的切換比進程之間的切換代價要小很多,也更加高效。在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
微信掃一掃
支付寶掃一掃