一、線程的概念
線程是指進程內部的一個執行單元,也稱為輕量級進程,它和進程一樣可以獨立執行、擁有獨立的棧空間、程序計數器和寄存器等,但是多個線程可以共享進程的資源,如內存空間、文件、I/O。線程的創建和銷毀都比進程更加的輕便快捷,因此多線程成為了提高系統性能和程序效率的一種重要方式。
二、線程的創建
Linux提供了幾種方式創建線程:pthread_create()、clone()等。其中pthread_create()是比較常用的一個函數,其函數原型如下:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
它的參數依次為:
1、指向線程標識符的指針;
2、線程屬性,NULL表示使用默認屬性;
3、指向函數的指針,該函數是新線程的入口地址;
4、函數的參數。
下面是一個簡單的例子:
#include #include #include void *print_message_function(void *ptr); int main() { pthread_t thread1, thread2; char *message1 = "Thread 1"; char *message2 = "Thread 2"; int ret1, ret2; // 創建線程1 ret1 = pthread_create(&thread1, NULL, print_message_function, (void *) message1); if (ret1 != 0) { printf("Create thread 1 failed!\n"); exit(1); } // 創建線程2 ret2 = pthread_create(&thread2, NULL, print_message_function, (void *) message2); if (ret2 != 0) { printf("Create thread 2 failed!\n"); exit(1); } pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf("Main function exits!\n"); return 0; } void *print_message_function(void *ptr) { char *message = (char *) ptr; printf("%s\n", message); }
在上面的例子中,我們使用pthread_create()函數創建了2個線程,並傳入一個字符串作為線程函數的參數。然後使用pthread_join()函數等待線程結束。
三、線程的同步
線程之間的同步通常需要互斥量、條件變量等機制。比如常用的互斥量pthread_mutex_t可以用來保護共享資源,pthread_cond_t則可以用來進行線程的條件等待與喚醒。
下面是一個使用互斥量保護共享資源的例子:
#include #include #include #define THREAD_NUM 5 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int sum = 0; void *thread_function(void *arg); int main() { pthread_t threads[THREAD_NUM]; // 創建多個線程 for (int i = 0; i < THREAD_NUM; i++) { pthread_create(&threads[i], NULL, thread_function, NULL); } // 等待所有線程結束 for (int i = 0; i < THREAD_NUM; i++) { pthread_join(threads[i], NULL); } printf("Sum = %d\n", sum); return 0; } void *thread_function(void *arg) { int i; for (i = 0; i < 1000; i++) { pthread_mutex_lock(&mutex); sum++; pthread_mutex_unlock(&mutex); } pthread_exit(NULL); }
在這個例子中,我們使用pthread_mutex_t來保護sum這個共享資源,多個線程會去累加這個值。由於多個線程同時訪問sum,如果沒有互斥保護,會產生競爭狀態,導致結果不正確。因此我們使用互斥量對共享資源進行保護,保證線程之間的同步。
四、線程的銷毀
線程的銷毀通常是在線程函數中通過pthread_exit()函數進行,也可以使用pthread_cancel()函數強製取消線程。同時可以使用pthread_join()函數等待線程結束,防止進程過早退出,導致線程沒有執行完畢。
下面是一個使用pthread_cancel()函數強製取消線程的例子:
#include #include #include void *thread_function(void *arg); int main() { pthread_t thread_id; int ret; // 創建線程 ret = pthread_create(&thread_id, NULL, thread_function, NULL); if (ret != 0) { printf("Create thread failed!\n"); exit(1); } // 睡眠 5 秒 sleep(5); // 強制殺死線程 pthread_cancel(thread_id); printf("Main function exits!\n"); return 0; } void *thread_function(void *arg) { int i; // 設置取消狀態 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); // 設置取消類型 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); for (i = 0; ; i++) { printf("Thread running...\n"); sleep(1); } pthread_exit(NULL); }
在上面的例子中,我們使用了pthread_cancel()函數強製取消線程。同時在線程函數中設置了取消狀態和取消類型。
五、線程的屬性
線程的屬性可以用來調整線程的優先級、棧大小等。pthread_attr_t是線程屬性的類型,Linux提供了一些函數來進行線程屬性的設置和獲取,如pthread_attr_init()、pthread_attr_setstacksize()、pthread_attr_getschedpolicy()等。
下面是一個設置線程棧大小的例子:
#include #include #include void *thread_function(void *arg); int main() { pthread_t thread_id; pthread_attr_t attr; size_t stacksize; int ret; // 初始化線程屬性 pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &stacksize); printf("Default stack size = %d KB\n", (int) stacksize / 1024); // 設置線程棧大小 pthread_attr_setstacksize(&attr, 1024 * 1024); pthread_attr_getstacksize(&attr, &stacksize); printf("New stack size = %d KB\n", (int) stacksize / 1024); // 創建線程 ret = pthread_create(&thread_id, &attr, thread_function, NULL); if (ret != 0) { printf("Create thread failed!\n"); exit(1); } // 等待線程結束 pthread_join(thread_id, NULL); printf("Main function exits!\n"); return 0; } void *thread_function(void *arg) { int i; for (i = 0; i < 10; i++) { printf("Thread running...\n"); sleep(1); } pthread_exit(NULL); }
在上面的例子中,我們使用了pthread_attr_setstacksize()函數設置了線程的棧大小為1MB。
六、總結
本文介紹了Linux下創建線程的方法及相關知識。具體來說,我們講解了線程的概念、創建、同步、銷毀和屬性等內容。通過本文的學習,讀者可以掌握如何使用Linux提供的相關函數來創建線程,並進行進一步的開發。
原創文章,作者:TOOK,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/143334.html