一、線程的概念
線程是指進程內部的一個執行單元,也稱為輕量級進程,它和進程一樣可以獨立執行、擁有獨立的棧空間、程序計數器和寄存器等,但是多個線程可以共享進程的資源,如內存空間、文件、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-tw/n/143334.html
微信掃一掃
支付寶掃一掃