linux之執行緒的高階屬性
一次性初始化: 用途: 有些事需要且只能執行一次(比如互斥量初始化)。通常當初始化應用程式時,可以比較容易地將其放在main函式中。但當你寫一個庫函式時,就不能在main裡面初始化了,你可以用靜態初始化,但使用一次初始(pthread_once_t)會比較容易些。 用法:
//首先要定義一個pthread_once_t變數,這個變數要用巨集PTHREAD_ONCE_INIT初始化。 //然後建立一個與控制變數相關的初始化函式 pthread_once_t once_control = PTHREAD_ONCE_INIT; void init_routine( ) { //需要初始化的內容 ...... } //最後,在任何時刻呼叫pthread_once函式。 //在多執行緒程式設計環境下,init_routine()函式僅執行一次,究竟在哪個執行緒中執行是不定的,由核心排程來決定。 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
執行緒的屬性:
執行緒的屬性型別:pthread_attr_t
屬性名稱 | 描述 |
detachstate | 執行緒的分離狀態 |
guardsize | 執行緒棧末尾的警戒區域大小(位元組數) |
stacksize | 執行緒棧的最低地址 |
stacksize | 執行緒棧的大小(位元組數) |
1、執行緒屬性初始化 int pthread_attr_init(pthread_attr_t *attr); 2、執行緒屬性銷燬 int pthread_attr_destroy(pthread_attr_t *attr);
執行緒的分離屬性:
1、分離屬性的概念 分離一個正在執行的執行緒並不影響它,僅僅是通知當前系統該執行緒結束時,其所屬的資源可以回收。一個沒有被分離的執行緒在終止時會保留它的虛擬記憶體,包括他們的堆疊和其他系統資源,有時這種執行緒被稱為“殭屍執行緒”。建立執行緒時預設是非分離的 如果執行緒具有分離屬性,執行緒終止時會被立刻回收,回收將釋放掉所有線上程終止時未釋放的系統資源和程序資源。包括儲存執行緒返回值的記憶體空間、堆疊、儲存暫存器的記憶體空間等
2、分離屬性的使用方法 如果在建立執行緒的時候就知道不需要了解執行緒的終止狀態,那麼可以修改pthread_attr_t結構體的detachstate屬性,讓執行緒以分離狀態啟動。
//設定執行緒分離屬性的步驟
//1、定義執行緒屬性變數
pthread_attr_t attr
// 2、初始化attr
pthread_attr_init(&attr)
//3、設定執行緒的分離狀態屬性
//執行緒的分離屬性有兩種合法值:PTHREAD_CREATE_DETACHED分離的 PTHREAD_CREATE_JOINABLE 非分離的,可連線的
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
//4、建立執行緒
int pthread_create(&tid, &attr, thread_fun, NULL)
獲得執行緒的分離狀態屬性
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
執行緒的棧屬性:
1、執行緒的棧大小 對於程序來說,虛擬地址空間的大小是固定的,程序中只有一個棧,因此它的大小通常不是問題。但對執行緒來說,同樣的虛擬地址被所有的執行緒共享。如果應用程式使用了太多的執行緒,致使執行緒棧累計超過可用的虛擬地址空間,這個時候就需要減少執行緒預設的棧大小。另外,如果執行緒分配了大量的自動變數或者執行緒的棧幀太深,那麼這個時候需要的棧要比預設的大。因此就需要修改執行緒棧的屬性來適應具體程式的需要。
>檢查系統是否支援執行緒棧屬性 1)在編譯階段使用 _POSIX_THREAD_ATTR_STACKADDR 和 _POSIX_THREAD_ATTR_STACKSIZE符號 來檢查系統是否支援執行緒棧屬性,這些巨集定義在/usr/include/bits/posix_opt.h 2)在執行階段把 _SC_THREAD_ATTR_STACKADD和 _SC_THREAD_THREAD_ATTR_STACKSIZE 傳遞給sysconf函式檢查系統對執行緒棧屬性的支援。
如果用完了虛擬地址空間,可以使用malloc或者mmap來為其他棧分配空間,並修改棧的位置。 >修改棧屬性 int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize); >獲取棧屬性 int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t * stacksize);
也可以單獨獲取或者修改棧的大小,而不去修改棧的地址。棧大小設定,不能小於PTHREAD_STACK_MIN(需要標頭檔案limit.h) >修改棧大小 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); >獲取棧大小 int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
2、棧尾警戒區 執行緒屬性guardsize控制著執行緒棧末尾以後用以避免棧溢位的擴充套件記憶體的大小,這個屬性預設是PAGESIZE個位元組。你可以把它設為0,這樣就不會提供警戒緩衝區。同樣的,如果你修改了stackaddr,系統會認為你自己要管理棧,警戒緩衝區會無效
1)、設定guardsize int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); 2)、獲取guardsize int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
例項:
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<limits.h>
pthread_attr_t attr;
void *thread_1(void * arg)
{
long signed int stacksize;
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
pthread_attr_getstacksize(&attr,&stacksize);
printf("thread1: default stacksize is %ld\n",stacksize);
pthread_attr_setstacksize(&attr,100000);
pthread_attr_getstacksize(&attr,&stacksize);
printf("thread1: personic stacksize is %ld\n",stacksize);
pthread_attr_setstacksize(&attr,PTHREAD_STACK_MIN);
pthread_attr_getstacksize(&attr,&stacksize);
printf("thread1: minimum stacksize is %ld\n",stacksize);
#endif
printf("I am thread1\n");
return (void *)1;
}
void *thread_2(void * arg)
{
printf("I am thread2\n");
return (void *)2;
}
int main(int argc,char *argv[])
{
pthread_t tid1,tid2;
int err1,err2;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//#ifdef _POSIX_THREAD_ATTR_STACKSIZE
// pthread_attr_setstacksize(&attr,PTHREAD_STACK_MIN);
//#endif
err1 = pthread_create(&tid1,&attr, thread_1,NULL);
err2 = pthread_create(&tid2,NULL, thread_2,NULL);
if(err1||err2)
{
printf("create thread fail\n");
return -1;
}
printf("thread1 return value is %d\n",pthread_join(tid1,NULL));
printf("thread2 return value is %d\n",pthread_join(tid2,NULL));
pthread_attr_destroy(&attr);
return 0;
}
執行結果:
[email protected]:~/my_share/pthread$ ./a.out
thread1 return value is 22
thread1: default stacksize is 8388608
thread1: personic stacksize is 100000
thread1: minimum stacksize is 16384
I am thread1
I am thread2
thread2 return value is 0