標籤:操作 線程 屬性控制 struct
線程屬性
屬性值不能直接設定,須使用相關函數進行操作
初始化函數為pthread_attr_init,該函數必須在pthread_create函數之前調用
typedef struct{ int detachstate; // 線程的分離狀態 int scope; // 線程綁定狀態 int schedpolicy; // 線程調度策略 struct sched_param schedparam; // 線程的調度參數 int inheritsched; //線程的繼承性 size_t guardsize; // 線程棧末尾的警戒緩衝區大小 void * stackaddr; // 線程棧的位置 size_t stacksize; // 線程棧的大小}pthread_attr_t;
刪除線程屬性對象
函數原型int pthread_attr_destroy(pthread_attr_t *attr); 傳回值成功返回0出錯,返回其他值說明刪除屬性對象佔用的記憶體調用這個函數後,相應的屬性對象無效
線程分離狀態(detachstate)
決定線程以何種方式終止自己非分離狀態原有的線程等待建立的線程結束只有當pthread_join()函數返回時,建立的線程才算終止,才能釋放自己佔用的系統資源分離線程沒有被其他的線程所等待,自己運行結束後終止線程,馬上釋放系統資源線程分離狀態相關函數pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)detachstate選值PTHREAD_CREATE_DETACHED(分離線程) PTHREAD _CREATE_JOINABLE(非分離線程)int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
線程綁定scope
輕量級進程
可理解為核心線程,位於使用者層和系統層之間
系統通過輕量級進程實現對線程資源的分配、對線程的控制
一個輕量級進程可以控制一個或多個線程
非綁定
啟動多少輕量級進程、哪些輕量級進程來控制哪些線程由系統來控制
系統的預設處理方式
綁定
某個線程固定的“綁”在一個輕量級進程之上
被綁定的線程具有較高的響應速度,這是因為CPU時間片的調度是面向輕進程的,綁定的線程可以保證在需要的時候它總有一個輕進程可用
通過設定被綁定的輕進程的優先順序和調度級可以使得綁定的線程滿足諸如即時反應之類的要求
線程綁定屬性設定函數
函數原型pthread_attr_setscope(pthread_attr_t * attr, int scope)參數說明attr:指向屬性結構的指標scope:綁定類型PTHREAD_SCOPE_SYSTEM(綁定的)PTHREAD_SCOPE_PROCESS(非綁定的)舉例/*初始化屬性值,均設為預設值*/pthread_attr_init(&attr); pthread_attr_setscope(&attr, THREAD_SCOPE_SYSTEM);pthread_create(&tid, &attr, (void *) my_function, NULL);
線程調度策略schedpolicy
函數原型int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);參數說明attr:線程屬性變數policy:調度策略SCHED_FIFO:先進先出SCHED_RR:輪轉法SCHED_OTHER:其它傳回值成功返回0失敗返回-1
線程調度參數schedparam
函數原型int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);參數說明attr:線程屬性param:sched_param結構sched_priority:控制一個優先權值sched_get_priority_min():擷取系統支援的最小優先權值sched_get_priority_max ():擷取系統支援的最大優先權值
線程的繼承性inheritsched
設定繼承調度策略PTHREAD_INHERIT_SCHED(預設值) 建立的線程將具有父線程的調度策略屬性對象中的調度策略參數將不起作用PTHREAD_EXPLICIT_SCHED線程的調度策略和父線程無關屬性對象中的調度策略參數將起作用相關設定函數int pthread_attr_setinheritsched(pthread_attr_t *tattr, int inherit); int pthread_attr_getinheritsched(pthread_attr_t *tattr, int *inherit);
堆棧防護區guardsize
預設情況下,線程的堆棧保護區大小因系統版本不同而異取值說明若guardsize=0,建立線程時將不會建立堆棧保護區若guardsize>0,建立線程時將至少有一個guardsize大小的堆棧保護區使用說明建立線程堆棧時,一般將guardsize參數值上舍入成系統變數PAGESIZE的整數倍,來分配堆棧保護區但程式調用pthread_attr_getguardsize()函數獲得的堆棧保護區大小將是調用pthread_attr_setguardsize()函數時指定的guardsize參數值相關函數int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize);
線程堆棧的基地址 stackaddr
預設由系統分配如果stackaddr為非空值,線程堆棧將從指定地址開始如果是NULL (預設值) ,pthread_create()為其分配堆棧 相關函數int pthread_attr_setstackaddr(pthread_attr_t *tattr, void *stackaddr); int pthread_attr_getstackaddr(pthread_attr_t *tattr, void **stackaddr);
線程堆棧大小stacksize
定義系統為線程分配的堆棧大小(位元組)預設由系統決定大小函數原型int pthread_attr_setstacksize(pthread_attr_t *tattr, int size); int pthread_attr_getstacksize(pthread_attr_t *tattr, size_t *size); 參數說明size:線程所需堆棧的大小size=0,系統使用預設大小在大多數情況下,預設值是最合適的堆棧的大小不能小於系統定義的最小堆棧容量PTHREAD_STACK_MIN
線程的一次性初始化
有時需要對一些posix變數只進行一次初始化(如線程鍵),如果多次初始化,程式就會出現錯誤
在順序編程中,常使用布爾變數來一次性初始化
控制變數被靜態初始化為0,任何依賴於初始化的代碼都能測試該變數
如果變數值仍然為0,則它能實行初始化,然後將變數置為1,以後檢查的代碼將跳過初始化
但在多線程程式設計中,事情變得非常複雜
如果多個線程並發地執行初始化序列代碼,兩個線程可能發現控制變數為0,並且都實行初始化,而該過程本該僅僅執行一次
初始化的狀態必須由互斥量保護
對一個posix靜態變數的初始化,可使用用一個互斥量對該變數的初始化進行控制
但使用pthread_once對變數進行動態初始化會方便許多
線程的一次性初始化函數
函數原型
pthread_once_t once_control=PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control, void(*init_routine)(void));
參數
once_control:控制變數,必須使用PTHREAD_ONCE_INIT宏靜態地初始化
init_routine:初始化函數
說明
pthread_once函數首先檢查控制變數,判斷是否已經完成初始化
如果完成,則返回
否則,調用初始化函數,並且記錄初始化被完成
如果在一個線程初始時,另外的線程調用pthread_once,則調用線程等待,直到那個線程完成初始化返回
線程的私人資料
背景
進程內的所有線程共用相同地址空間,任何聲明為靜態或外部的變數,或在進程堆聲明的變數,都可以被進程所有的線程讀寫
怎樣才能使線程式擁有自己的私人資料?
函數原型
int pthread_key_create(pthread_key key, void(*destructor)(void ));
參數
key:私人資料鍵
destructor:清理函數
如果該參數不為空白,則當每個線程結束時,系統將調用這個函數來釋放綁定在這個鍵上的記憶體塊
說明
函數從線程私人資料池中分配一項,將其值賦給key供以後訪問使用
無論哪個線程調用pthread_key_create(),所建立的key都是所有線程可訪問的,但各個線程可根據自己的需要往key中填入不同的值,這就相當於提供了一個同名而不同值的全域變數
該函數常和函數pthread_once一起使用,以便該鍵只被建立一次
函數原型int pthread_setspecific(pthread_key_t key, const void *pointer) void * pthread_getspecific(pthread_key_t key) 說明pthread_setspecific()將pointer的值(不是所指的內容)與key相關聯pthread_getspecific()將與key相關聯的資料讀出來資料類型都設為void *,因此可以指向任何類型的資料
說明
建立兩個線程分別設定同一個線程私人資料為自己的線程ID
為了檢驗其私人性,程式錯開了兩個線程私人資料的寫入和讀出的時間
從程式運行結果可以看出,兩個線程對TSD的修改互不干擾
當線程退出時,清理函數會自動執行,參數為tid
Linux - 線程屬性控制