目錄
1.進程和線程的概念
2.線程內核三級映射
3.線程優缺點
4.創建線程和獲取線程ID的函數
5.創建子線程
6.循環創建N個子線程
7.子線程傳參地址錯誤演示分析
8.主、子線程共享全局變量、堆空間
9.線程退出
10.pthread join回收線程退出值
11.pthread_cancel
12.殺死線程pthread_cancel
13.進程線程對比
14.線程屬性簡介
1.進程和線程的概念
-?Linux 系統中,線程 LWP 稱之為:輕量級的進程。
-?進程:有獨立的進程地址空間, 有獨立的 pcb。 —— 最小資源分配單位。
-?線程:有獨立的pcb,沒有獨立的進程地址空間。(與其他線程共享) —— 最小執行單位。

-?一個創建了線程的進程,本身也淪落 為線程。

-?LWP 號: cpu 劃分時間片依據。??—— 線程 最小執行單位。
????-?查看LWP號命令: ps -Lf 進程pid?
2.線程內核三級映射
3.線程優缺點
-?優點:
????-?并發性強。??
????-?開銷小。
????-?數據通信方便。
-?缺點:
????-?庫函數,穩定性差。
????-?調試、編寫困難
????-?對信號支持差。
-?結論:既能使用進程開發,也能使用線程開發的程序,首選 線程。
4.創建線程和獲取線程ID的函數
```c
#include <pthread.h>
pthread_t pthread_self(void);???// 獲取線程id, 在進程內部標識線程身份。
返回線程id。 沒有錯誤!
```
5.創建子線程
```c
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
??????????????????????????void *(*start_routine) (void *), void *arg);
參1: 傳出參數,新子線的 線程id
參2: 線程屬性。默認傳 NULL, 表使用默認屬性。
參3: 子線程回調函數。pthread_create 調用成功,該函數會被自動調用起來。
參4: 參3 的參數。
返回值:
????成功:0
????失敗:直接返回錯誤號!
6.循環創建N個子線程
```c
// 子線程主函數
void *tfn(void *arg)
{
????printf("tfn : pid = %d, pthread_id = %lu\n", getpid(), pthread_self());
????return NULL;
}
int main(int argc, char *argv[])
{
????pthread_t tid;
????// 創建子線程
????int ret = pthread_create(&tid, NULL, tfn, NULL);
????if (ret != 0)
????????fprintf(stderr, "pthread_create err:%s\n", strerror(ret));
????printf("main : pid = %d, pthread_id = %lu\n", getpid(), pthread_self());
????sleep(1);????????// 給子線程執行時間
????return 0;????????// 釋放
7.子線程傳參地址錯誤演示分析
8.主、子線程共享全局變量、堆空間
// 阻塞 回收線程。
int pthread_join(pthread_t thread, void **retval);
參1:待回收的線程id
參2:傳出參數。回收的那個線程的 退出值。
????進程中:main返回值:return 0、 exit(1)??---> int。 回收進程退出值 wait(int *)
????線程中:線程返回值:pthread_exit --> void *。 回收線程退出值 pthread_join(void **)
返回值:
????成功:0
????失敗:直接返回錯誤號!
```
9.線程退出
```c
// 子線程主題函數
void *tfn(void *arg)
{
????sleep(5);
????//return (void *)74;
????pthread_exit((void *)"hello");
}
int main(int argc, char *argv[])
{
????pthread_t tid;
????//int *retval;????// 用來存儲子進程退出值
????char *retval;????// 用來存儲子進程退出值
????// 創建子線程
????int ret = pthread_create(&tid, NULL, tfn, NULL);
????if (ret != 0)
????????fprintf(stderr, "pthread_create err:%s\n", strerror(ret));
????printf("----------------1\n");
????// 回收子線程退出值
????ret = pthread_join(tid, (void **)&retval);
????if (ret != 0)
????????fprintf(stderr, "pthread_join err:%s\n", strerror(ret));
????printf("child thread exit with %s\n", (char *)retval);
????pthread_exit((void *)0);????????// 退出主線程
}
10.pthread join回收線程退出值
```c
struct thrd {
????int var;
????char str[256];
};
// 子線程主題函數
void *tfn(void *arg)
{
????struct thrd *tval = (struct thrd *)arg;????????????//malloc()
????tval->var = 100;
????strcpy(tval->str, "hello thread");
????pthread_exit((void *)tval);
????// return (void *)tval;????????????????// 也可以
}
int main(int argc, char *argv[])
{
????pthread_t tid;
????struct thrd arg, *retval;
????// 創建子線程
????int ret = pthread_create(&tid, NULL, tfn, (void *)&arg);
????if (ret != 0)
????????fprintf(stderr, "pthread_create err:%s\n", strerror(ret));
????// 回收子線程退出值
????ret = pthread_join(tid, (void **)&retval);
????if (ret != 0)
????????fprintf(stderr, "pthread_join err:%s\n", strerror(ret));
????
????printf("child exit with: var = %d, str= %s\n", retval->var, retval->str);
????// free();
????
????pthread_exit((void *)0);????????// 退出主線程
}
```
11.pthread_cancel
-?與進程類似,線程結束時,也有 “僵尸線程” 產生。消耗系統資源。
```c
int pthread_detach(pthread_t thread);??// 設置線程為分離態。
參:待設置為分離的線程id
```
-?設置為 分離態的 線程,在終止時,會自動清理 pcb 內核殘留。
-?對于已經分離的線程,使用 pthread_join() 不能正常回收。不能獲取線程退出值。
12.殺死線程pthread_cancel
``c
int pthread_cancel(pthread_t thread);
參:待殺死的線程id
```
1.?被 pthread_cancel() 殺死的線程,在使用 pthread_join() 回收,得到的退出值 -1。?
2.?pthread_cancel() 殺死線程必須要到達一個 “取消點” (保存點), 才能生效。否則無法殺死線程。
????-?應該在被cancel的線程中,調用 pthread_testcancel() 函數 來 添加 “取消點” (保存點)。
13.進程線程對比
1.?return
2.?pthread_exit()
3.?pthread_cancel()???需要 “保存點”。 —— 進內核,即可得到。
14.線程屬性簡介
| 線程控制原語?????| 進程控制原語???|
| ---------------- | -------------- |
| pthread_create() | fork()?????????|
| pthread_self()???| getpid()???????|
| pthread_exit()???| exit()?????????|
| pthread_join()???| wait/waitpid() |
| pthread_cancel() | kill()?????????|
| pthread_detach() |????????????????|
?