在處理某些問題時,有時候會通過生成子程序來實現,但是,程序是昂貴的,利用子程序來處理相關問題需要很大的開銷,因此有時候需要執行緒來處理,執行緒可以看成的輕量的程序。
同一程序內的執行緒共享以下資料:
每個執行緒有各自的:
當乙個執行緒以exec執行時,稱為主線程或初始執行緒的執行緒就已經建立了,其他的執行緒由函式pthread_create() 建立。
// 返回值:成功則為0,出錯為相應的error值;
#include
int pthread_create((pthread_t *thread, pthread_attr_t *attr, void *(*func)(void *), void *arg)
說明:thread:執行緒識別符號;
attr:執行緒屬性設定;一般為null預設;
arg:傳遞給func的引數;
返回值:成功,返回0;出錯,返回-1;
pthread_t: int or long ;
pthread_attr_t: 屬性結構體;
在任何乙個時間點上,執行緒是可結合的(joinable)或者是分離的(detached)。乙個可結合的執行緒能夠被其他執行緒收回其資源和殺死。在被其他執行緒**之前,它的儲存器資源(例如棧)是不釋放的。相反,乙個分離的執行緒是不能被其他執行緒**或殺死的,它的儲存器資源在它終止時由系統自動釋放。預設情況下,執行緒被建立成可結合的。為了避免儲存器洩漏,每個可結合執行緒都應該要麼被顯示地**,即呼叫pthread_join;要麼通過呼叫pthread_detach函式被分離。
int pthread_join(pthread_t tid, void **status)
功能:等待乙個給定執行緒tid終止;status非空則儲存tid返回值
返回值:成功則為0,出錯為相應的error值;
int pthread_detach(pthread_t tid);
功能:把指定的執行緒tid轉為脫離狀態;tid用於表示執行緒id標識,status若非空,則儲存所等待執行緒的返回值;只能等待指定id的執行緒,類似於程序中的waitpid函式;
說明:可以pthread_detach(pthread_self())來使自己分離,pthread_self返回本身的執行緒id;
返回值:成功則為0,出錯為相應的error值;
void pthread_exit(void *status);
功能: 退出執行緒;
int pthread_kill(pthread_t thread, int sig);
功能: 給執行緒thread傳送乙個訊號:sig;
說明: 接收訊號的執行緒必須先用sigaction函式註冊該訊號的處理函式;
pthread_t pthread_self(void);
函式作用:獲得執行緒自身的id。pthread_t的型別為unsigned
long
int,所以在列印的時候要使用%lu方式,否則顯示結果出問題。
執行緒中許多資料都是共享的,因此需要對共享資料進行相關的處理,防止執行緒間對共享資料進行非正常訪問和修改。主要的方式有互斥鎖、條件變數、訊號量等。
互斥鎖互斥鎖:訪問共享變數前需要先獲取互斥鎖,用於保護變數,使之在被乙個執行緒使用時不被其它執行緒訪問。
當乙個執行緒獲取了互斥鎖,那麼它將獨享這個鎖,對共享資料具有操作資格,其它執行緒在此時無法獲取這個互斥鎖,也就無法對共享資料進行操作,只有當這個鎖被釋放,其它執行緒才能夠開始競爭獲取這個鎖;也就是說在同一時刻,只有乙個執行緒處於執行狀態,其它的則在等待獲取互斥鎖或其它處理過程中。互斥鎖用pthread_mutex_t型別的資料變數來表示,使用前必須先進行初始化,可以將之設定為常量pthread_mutex_initializer,也可以通過函式pthread_mutex_init初始化,如果互斥鎖是動態分配的,則在釋放記憶體前需要呼叫pthread_mutex_destroy;
int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr);
功能:初始化乙個互斥鎖mutex;
說明:使用預設屬性則attr設為null;
返回值:成功返回0,錯誤相應編號;
pthread_mutex_t: 互斥鎖型別結構;
pthread_mutexattr_t: 互斥鎖屬性結構;
int pthread_mutex_destory(pthread_mutex_t *mutex );
功能: 丟棄(釋放)乙個互斥鎖mutex;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能: 分別為獲取鎖,嘗試獲取鎖,解鎖
說明: 引數mutex表示對應的互斥鎖指標;第二個函式呼叫不會阻塞執行緒,若互斥鎖還沒有被上鎖,那麼執行緒獲取這個鎖,否則返回ebusy,執行緒不會一直阻塞直到獲取互斥鎖;其它兩個函式一直阻塞直到成功返回;
返回值:成功返回0,錯誤相應編號;
互斥鎖的作用其實就是在**中建立乙個臨界區域,當執行緒需要訪問乙個共享變數時,先獲取互斥鎖,然後再進行操作,操作完畢之後,再釋放該互斥鎖;所有的執行緒在處理共享變數前都要執行相同的操作,這樣保證了變數在同一時刻只被乙個執行緒處理。簡單示例:
#include
#include
#include
#define n 50
int counter;
pthread_mutex_t counter_mutex = pthread_mutex_initializer;
void *doit(void *arg);
int main(int argc, char **argv)
void *doit(void *arg)
return
null;
}
可以看到,上面的兩個執行緒在處理共享值counter之前都需要先獲取鎖。
注意在編譯此檔案時,需要新增引數-lpthread,原因在於pthread不是linux的預設庫,參考pthread_create編譯問題;
讀寫鎖:讀寫鎖與互斥量類似,但允許更高的並行性,有3種狀態:讀模式下加鎖,寫模式下加鎖,不加鎖,一次只有乙個執行緒可以占有寫模式的加鎖狀態,多個執行緒可以占有讀模式的加鎖狀態。適合資料結構讀的次數遠大於寫的情況。
自旋鎖:與互斥量類似,不通過休眠使執行緒阻塞,而在在獲取鎖之前處於忙等(自旋)阻塞狀態。可用於:鎖被持有的時間短,執行緒不希望在重新呼叫上花費太多成本。
條件變數
條件變數是另一種同步機制,通過條件來決定執行緒是否程序等待。即乙個執行緒執行時需要滿足某些條件才執行,但是通過不斷的迴圈來判斷條件是否滿足這樣十分的佔資源,可以通過乙個條件變數來實現;即建立乙個條件變數,當當前執行緒獲取到互斥鎖之後,執行到某一步就檢查條件變數(此時程序釋放鎖,其它程序獲取該鎖並執行操作,當操作完畢,釋放鎖並返回乙個訊號,通知前面的執行緒條件變數滿足,之前的執行緒就再一次獲取互斥鎖,繼續執行後面的操作,實質上是本執行緒是否繼續執行由其它執行緒來決定),當條件變數滿足,繼續執行。
條件變數用pthread_cond_t類似的資料表示,通過下面的函式進行初始化和銷毀;
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
功能: 初始化乙個條件變數cond;
說明:attr為屬性指標,一般使用預設直接設為null;可以用常量pthread_cond_initializer來賦給靜態分配的條件變數;
返回值:成功則為0,失敗為錯誤編號;
pthread_cont_t: 條件變數結構
const pthread_condattr_t:條件變數屬性結構
int pthread_cond_destory(pthread_cond_t *cond);
功能: 銷毀乙個條件變數;
int pthread_cond_signal(pthread_cond_t *cond);
功能:傳送乙個訊號給另外乙個正在處於阻塞等待狀態的執行緒,使其脫離阻塞狀態,繼續執行,如果沒有執行緒處在阻塞等待狀態,pthread_cond_signal也會成功返回。
返回值:成功則為0,失敗為錯誤編號;
int pthread_cond_broadcast(pthread_cond_t *cond);
功能:喚醒所有等待該條件的執行緒;
返回值:成功則為0,失敗為錯誤編號;
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
功能:等待條件變數,過程中釋放鎖並阻塞;
說明:mutex為當前執行緒獲取的互斥鎖指標,函式先對互斥量解鎖,當條件變數滿足函式返回時,互斥量再次被鎖住;
返回值:成功0,失敗對應錯誤碼;
int pthread_cond_timedwait(pthread_cond_t *cond,
thread_mutex_t *mutex,
const timespec *abstime);
說明:與第乙個功能類似,但設定了條件的等待時間;當時間到了條件還沒有滿足,那麼重新獲取互斥鎖,返回錯誤etimedout;abstime是乙個絕對時間,即當前時間加上等待的時長;pthread_cond_timewait即便是在時間超時的情況下一定會等到真正重新獲得mutex之後才會返回。
參考: 在linux中使用執行緒 ;
mutex和condition variable的區別是 mutex只能實現互斥訪問,但不能對資源計數啊,所以當有多個生產者和消費者時,只能用cond。
執行緒池簡單介紹
執行緒池 1 fixedthreadpool 可重用固定執行緒數的執行緒池 2 singlethreadexecutor 單個worker執行緒的executor 3 cachedthreadpool 根據需要建立執行緒的執行緒池 corepoolsize為0,maximumpoolsize是無界的...
Linux簡單介紹
說到linux不得不說下unix,兩者操作起來差不多,linux的開發也借鑑了unix很多東西.計算機的發展史非常短.如果從1946第一台電子計算機eniac算起,才67年.剛好跟新中國的歷史差不多.當然了1946的之前已經有過很多跟計算機相關的研究和簡單應用了.對我們普通的程式設計師來說,在浩如煙...
Linux簡單介紹
在我們的專案開發完全之後,我們只能在內網訪問,要怎麼樣才能實現公網訪問呢?我們需要把我們的專案打包傳送到專業的伺服器上面才能實現公網訪問 軟體伺服器 web伺服器,把寫好的web資源共享到網路之中,方便別人能直接看到 硬體伺服器 安裝了伺服器軟體的電腦就是硬體伺服器 企業中的伺服器都是專業伺服器,每...