[17]APUE:線程

一般狀況下,線程模型的併發性能優於進程模型,但不老是這樣編程

線程的優點:多線程

  1. 線程的建立、銷燬及上下文切換代價比進程低
  2. 某些狀況下,使用線程能夠簡化邏輯,避免異步編程的複雜性
  3. 同一進程內全部線程共享全局內存段,沒有進程間通訊的開銷

線程的劣勢:併發

  1. 線程之間協做的順序(時序)是徹底隨機的,*nix 內核的實現中也不包括對線程時序的徹底控制,線程的不可控特性可能會帶來某些測試過程當中難以復現的 BUG,業務風險較高
  2. 線程之間的數據共享,同時也帶來了數據競爭的問題,須要十分謹慎地的處理臨界區數據

 *nix 平臺下的線程實現異步

  1. 在內核層面的實現中,線程本質上仍是進程模型,用戶空間看到的每一線程,都對應於內核中一個進程(lwp:light weight process),用戶空間的進程 ID,對應於內核層面的進程組 ID
  2. 線程的併發性能提高並不是線性增加,各類鎖機制的存在,都會形成線程併發性能的下降
  3. 多線程編程須要對特定硬件平臺的特性有更深刻的瞭解,不然容易陷入「僞共享」等硬件相關的性能瓶頸中

線程的建立與終止異步編程

#include <pthread.h>
//pthread_* 類的函數成功返回 0;出錯時,直接返回錯誤碼,同時也會設置 errno
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
void pthread_exit(void *retval);
pthread_t pthread_self(void);
  • pthread_self 函數用於線程取得自身的線程 ID
    • 此處的 ID 是用戶空間的概念,只在線程所屬的進程環境下有意義,一般狀況下就是一個指向特定結構體的內存地址(Linux/FreeBSD)
    • 操做系統範圍內能夠重複,同一進程中的線程退出後,其 ID 也能夠當即被複用
  • 線程執行函數中調用 return 也能夠終止自身

釋放線程所佔用的資源函數

#include <pthread.h>
int pthread_detach(pthread_t thread);
int pthread_join(pthread_t thread, void **retval);
  • 調用 pthread_detach(pthread_self()) 可以使線程自身處於 detach 處態,線程退出後,其佔用的資源將自動釋放
  • 同一進程環境中的其它線程可使用 pthread_join 函數得到指定線程的退出狀態,同時釋放其所佔用的資源

線程屬性設置性能

#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
  • 線程屬性設置使用 pthread_attr_t 數據類型,必須首先調用 pthread_attr_init 初始化以後才能使用,使用完成以後須要調用 pthread_attr_destroy 釋放資源
  • pthread_attr_setdetachstate 函數中 detachstate 參數的可選值有:PTHREAD_CREATE_JOINABLE、PTHREAD_CREATE_DETACHED,默認是前者,效果與線程自身調用 pthread_detach(pthread_self()) 相同

線程 ID 比較測試

int pthread_equal(pthread_t t1, pthread_t t2); 
  • 不一樣操做系統中的線程實現方式存在差別,不能直接用 '==' 判斷

線程清理函數spa

#include <pthread.h>
void pthread_cleanup_push(void (*cleanup_routine)(void *), void *arg);
void pthread_cleanup_pop(int execute);
  • 不一樣的操做系統中,pthread_cleanup_push 與 pthread_cleanup_pop 能夠實現爲宏或函數,使用時必須一一配對使用,執行順序與設置順序相反,與進程清理中的 atexit 函數相似
  • pthread_cleanup_pop 的參數爲 0 時,將不執行對應的清理行爲
  • 在實現爲宏的平臺上(如:FreeBSD、MAX OS),函數退出必須調用 pthread_exit,而不能使用 return 返回,不然清理動做將得不到執行
相關文章
相關標籤/搜索