國嵌視訊學習第六天——多執行緒
執行緒
優點
使用多執行緒的理由之一是:
和程序相比,它是一種非常“節儉”的多工操作方式。在Linux系統下,啟動一個新的程序必須分配給它獨立的地址空間,建立眾多的資料表來維護它的程式碼段、堆疊段和資料段,這是一種“昂貴”的多工工作方式
運行於一個程序中的多個執行緒,它們之間使用相同的地址空間,而且執行緒間彼此切換所需的時間也遠遠小於程序間切換所需要的時間
使用多執行緒的理由之二是:
執行緒間方便的通訊機制。對不同程序來說,他們具有獨立的資料空間,要進行資料的傳遞只能通過程序間通訊的方式進行,這種方式不僅費時,而且不方便。執行緒則不然,只需定義一個全域性變數。因為這個全域性變數是屬於程序的,而同一程序下的所有執行緒是共享資料空間的,所以一個執行緒的資料可以直接為其他執行緒所用
例如,之前所學的fork()函式,父子程序共享程式碼段,但是不共享資料段,而執行緒則是所有都是共享的
多執行緒程式作為一種多工、併發的工作方式,有如下優點:
---使多CPU系統更加有效。作業系統會保證當執行緒數不大於CPU數目時,不同的執行緒運行於不同的CPU上。
---改善程式結構。一個既長又複雜的程序可以考慮分為多個執行緒,分為幾個獨立或半獨立的執行部分,這樣的程式會利於理解和修改
多執行緒
LInux系統下的多執行緒遵循POSIX執行緒介面,稱為pthread。編寫linux西的多執行緒程式,需要使用標頭檔案pthread.h,連線時需要使用庫libpthread.a
建立執行緒
#include <pthread.h>
int pthread_create(pthread_t * tidp, const pthread_attr_t * attr, void*(*start_rtn)(void),void * arg)
---tidp:執行緒id
---attr:執行緒屬性(通常為空)
---start_rtn:執行緒要執行的函式。聲明瞭一個函式指標start_rtn,返回值為void *,引數是void
建立執行緒之後,執行緒處於就緒態,因此程序繼續執行下去(執行緒不執行)。
這裡和fork是不同的。fork()函式呼叫後,子程序執行的是fork()
---arg:start_rtn的引數
其實pthread其實質是一個整數。
---如果返回值是真,那麼表示建立錯誤
編譯
因為pthread的庫不是linux系統的庫,所以在進行編譯的時候要加上 -lpthread
#gcc filename1 -lpthread -o filename2
例thread_create.c thread_int.c thread_string.c thread_struct.c thread_share.c
終止執行緒
如果程序中任何一個執行緒中呼叫exit或_exit,那麼整個程序都會終止。執行緒的正常退出方式有:
(1).執行緒從啟動例程中返回(比如return)
(2).執行緒可以被另一個程序終止
(3).執行緒自己呼叫pthread_exit函式
執行緒退出
#include <pthread.h>
void pthread_exit(void *rval_ptr)
功能:終止呼叫執行緒
rval_ptr:執行緒退出返回值的指標
例thread_exit.c
執行緒等待
#inlude <pthread.h>
int pthread_join(pthread_t tid, void **rval_ptr);
功能:阻塞呼叫執行緒,直到指定的執行緒終止。
tid:等待退出的執行緒id
rval_ptr:為一個使用者定義的指標,它可以用來儲存被等待執行緒的返回值
這個函式是一個執行緒阻塞的函式,呼叫它的函式將一直等待到被等待的執行緒結束為止,當函式返回時,被等待執行緒的資源被收回。如果執行成功,將返回0,如果失敗則返回一個錯誤號
這與程序的等待不同,程序的等待是wait()
例thread_join.c
執行緒標識
#include <pthread.h>
pthread_t pthread_self(void)
功能:獲取呼叫執行緒的thread identifier
例thread_id.c
清除
執行緒終止有兩種情況:正常終止和非正常終止。執行緒主動呼叫pthread_exit或者從執行緒函式中return都將使執行緒正常退出,這是可預見的退出方式;非正常終止是執行緒在其他執行緒的干預下,或者由於自身執行出錯(比如訪問非法地址)而退出,這種退出方式是不可預見的。
不論是可預見的執行緒終止還是異常終止,都會存在資源釋放的問題,如何保證執行緒終止時能順利的釋放掉自己所佔用的資源,是一個必須考慮解決的問題。
從pthread_cleanup_push的呼叫點到pthread_cleanup_pop之間的程式段中的終止動作(包括呼叫pthread_exit()和異常終止,不包括return)都將執行pthread_cleanup_push()所指定的清理函式。即在這段程式碼中有任何上述終止的語句,那麼在執行該終止語句之前將呼叫pthread_cleanup_push()指定的函式(而該終止語句還將繼續執行下去)。
#include <pthread.h>
void pthread_cleanup_push(void(*rtn)(void *), void *arg)
功能:將清除函式壓入清除棧
---rtn:清除函式
---arg:清除函式的引數
void pthread_cleanup_pop(int execute)
功能:將清除函式彈出清除棧
---execute:execute執行到pthread_cleanup_pop()時是否在彈出清理函式的同時執行該函式,非0:執行;0:不執行
例thread_clean.c