线程以及pthread库的使用
https://blog.csdn.net/weixin_38102771/article/details/91351126
https://blog.csdn.net/qq_29677867/article/details/108571388?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242
一.什么是線程
你可以想象你一邊聽歌一邊打游戲,如果是操作系統會怎么做呢?先執行 ListenMusic 再執行 PlayGame,還是先執行 PlayGame 再執行 ListenMusic 呢?好像都不太合適。為了實現這個目的,就需要引入線程這個概念。線程是 CPU 調度的最小執行單位,你可以創建一個線程用于 ListenMusic,再創建一個線程去 PlayGame,這樣操作系統就是同時處理這兩個任務的(并發)。
二.pthread庫
(1) 使用說明
POSIX 標準定義了一套線程操作相關的函數,用于讓程序員更加方便地操作管理線程,函數名都是以前綴 pthread_ 開始,使用時要包含 <pthread.h>,而且在鏈接的時候要手動鏈接 pthread 這個庫,如:gcc main.c -lpthread -o main。
(2) 常用函數
函數原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
功能說明:創建一個線程。
參數說明
thread:線程句柄,需要先定義一個 pthread_t 類型變量 thread,將該變量的地址 &thread 傳遞到該參數中去。這是一個傳出參數,傳遞進去的 thread 會得到系統為我們創建好的線程句柄。
attr:線程屬性,通過該參數可以設置創建的線程屬性,如果要使用默認屬性直接傳遞 NULL 即可。
start_routine:線程函數,它是一個函數指針類型,返回類型為 void *,參數為一個 void * 類型變量,創建好這樣類型的一個函數,將函數名傳遞進去即可。
arg:線程參數,代表需要在主線程傳遞給子線程的參數,給 arg 賦值后可以在線程函數的參數中取到。
返回值說明
成功情況下返回 0,失敗情況下返回錯誤碼,并且 tid 的值是不確定的。Linux 環境下所有線程函數調用失敗時均是返回錯誤碼,除了部分返回值為 void 的函數。關于錯誤碼的說明在這里的第 8 小節。函數原型:pthread_t pthread_self(void);
功能說明:獲取線程 ID。
參數說明:無參數。
返回值說明:如果在主線程中調用該函數會返回主線程的線程 ID,如果在子線程中調用該函數會返回子線程的線程 ID,該函數沒有失敗的情況。
額外說明:線程 ID 是進程內部識別標志,兩個進程間線程 ID 允許相同。
函數原型:int pthread_equal(pthread_t t1, pthread_t t2);
功能說明:比較兩個線程 ID 是否相等,在 Linux 系統中 pthread_t 都設計為 unsigned long 類型,所以可以直接用 == 判別是否相等,但是如果某些系統設計為結構體類型,那么就可以通過 pthread_equal 函數判別是否相等了。
參數說明:要比較的兩個線程 ID。
返回值說明:若相等返回非 0 數值,否則返回 0。
函數原型:void pthread_exit(void *retval);
功能說明:將單個線程退出。
參數說明:retval 為該線程的返回狀態,如果主線程調用 pthread_join 可以獲取到該返回狀態。
返回值說明:void。
額外說明:如果在主線程中調用了 pthread_exit(NULL),則主線程退出,如果子線程存在會繼續執行。如下代碼,就算主線程先退出了,也不會影響子線程打印"我是子線程"。注意如果使用 exit 退出會導致整個進程結束。
函數原型:int pthread_join(pthread_t thread,void **retval);
功能說明:阻塞等待線程退出,獲取線程退出狀態,相當于進程中的 waitpid 函數,如果線程退出,pthread_join 立刻返回。
參數說明
thread:代表要等待線程的線程 ID
retval:獲取該線程的退出狀態
返回值說明
成功情況下返回 0,失敗則返回錯誤碼。函數原型:int pthread_detach(pthread_t thread);
功能說明:將線程 ID 為 thread 的線程分離出去,所謂分離出去就是指主線程不需要再通過 pthread_join 等方式等待該線程的結束并回收其線程控制塊(TCB)的資源,被分離的線程結束后由操作系統負責其資源的回收。
參數說明:thread 為要分離的線程的線程 ID。
返回值說明
成功情況下返回 0,失敗情況下返回錯誤碼。額外說明
一般來說,主線程是要負責創建出來的子線程的資源回收工作的。如果主線程先于子線程退出并且子線程沒有設置為分離狀態,那么子線程結束后其資源是無法得到回收的,會造成資源浪費和系統臃腫;如果主線程先于子線程退出但是子線程時分離狀態,那么子線程退出的時候操作系統會自動回收其資源。函數原型:int pthread_cancel(pthread_t thread);
功能說明:殺死線程。
參數說明:thread 為要殺死的線程的線程 ID。
返回值說明:成功情況下返回 0,失敗情況下返回錯誤碼。
程序說明
分別創建了兩個線程,pthread_func3 是一個死循環。在主線程中 sleep(3) 之后調用 pthread_cancel 結束子線程 pthread_func3,再調用 pthread_join 回收該子線程,由于子線程已經被殺死,此時 pthread_join 返回 -1。如果在子線程中的 while(1) 里,將 printf 和 sleep 函數注釋掉,會發現殺不死該線程,原因是 pthread_cancel 并不等待線程終止,它僅僅提出了一種請求,需要子線程執行到特定的取消點才能終止該線程(如一些系統調用 write,pause 等地方)。如果線程中沒有系統調用的函數,可以加入 pthread_testcancel 函數作為取消點。EDEADLK:檢測到線程發生死鎖
EINVAL:線程不是可以等待回收的線程(后續會講到線程分離)或者有其他線程已經準備等待回收該線程了
ESRCH:該線程 ID 不存在
三.使用線程的好處
在 Linux 編程中,多線程編程無疑是十分重要的。它可以提高程序的并發處理能力,線程間通信和共享數據十分方便,而且相對于多進程來說,它更加輕量級、好用。
————————————————
版權聲明:本文為CSDN博主「夢別停」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_38102771/article/details/91351126
總結
以上是生活随笔為你收集整理的线程以及pthread库的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下java -version版
- 下一篇: Jfinal 显示欢迎页 index.j