一 線程(也稱爲輕量級的進程)數據結構
1.一、線程基本特色多線程
a)線程依賴於進程而存在,在一個進程裏面開出的多個線程共享同一進程空間,這樣利用多線程實現多任務時,就能避免由於大量頻繁的進程間切換而帶來的開銷。併發
b)每一個線程也一樣有一個task_truct結構體來描述,可是共享同一進程的全部線程共享入口地址異步
c)進程與線程都參與統一的內核調度(切換)。函數
d)線程的本質就是指針函數。post
1.二、線程好處spa
1)大大提升了進程間的切換效率線程
2)避免了沒必要要的TLB和cache刷新,節省了空間的消耗指針
1.三、線程的實現rest
1)不禁內核實現,而是由第三方線程庫實現的,編譯時須要鏈接才行
2)同一進程內的全部線程都會共享進程的哪些資源呢?
a)指令代碼
b)靜態數據(主要是用於線程間通訊用的全局變量)
c)進程打開的全部的文件描述符
d)進程的當前工做目錄
e)進程的實際用戶ID和有效用戶ID
f)實際組ID和有效組ID
3)每一個線程的私有資源有哪些?
a)線程ID(TID)
b)本身的PC(程序計數器值)和相關的狀態寄存器(存放該線程被切換時的狀態)
c)本身的局部變量(每一個線程其實就是一個函數),每一個線程都會從進程棧中開出本身的
線程棧(也可稱爲線程函數棧)
d)本身的錯誤號errno
e)本身的信號掩碼(屏蔽字,起初是繼承進程(主線程)的),和未決信號集(繼承於主線程,可是會被當即清空)
f)有本身的執行狀態
4)線程實現過程
a)建立線程,pthread_create函數
b)控制線程,pthread_join,pthread_detach,pthread_cancle,pthread_exit等函數
5)線程的資源保護
咱們知道,對於進程來講資源保護是自然的,由於它們擁有獨立虛擬內存空間,互相不能互訪,這也致使相互通訊也很不容易。可是對於同一進程內的多個線程來講,因爲它們共享進程的虛擬內存地址,所以它們相互之間能夠很容易地進行資源的共享,可是資源間的保護卻成爲了一個問題。線程資源保護機制有:
a)無名信號量(進程用的是有名信號量或稱爲系統V信號量)
b)線程間的互斥鎖
c)條件變量(一種線程間的異步通訊機制,相似於進程間的信號通訊)
6)注意,若是主線程先死,那麼全部次線程都會跟着死調,因此任何線程調了exit函數後整個進程將會結束
二 線程與進程
進程是程序執行時的一個實例,即它是程序已經執行到何種程度的數據結構的聚集。從內核的觀點看,進程的目的就是擔當分配系統資源(CPU時間、內存等)的基本單位。
線程是進程的一個執行流,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。一個進程由幾個線程組成(擁有不少相對獨立的執行流的用戶程序共享應用程序的大部分數據結構),線程與同屬一個進程的其餘的線程共享進程所擁有的所有資源。
"進程——資源分配的最小單位,線程——程序執行的最小單位"
進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。
具體異同看下錶:
三 相關函數
線程建立函數
intpthread_create(pthread_t*thread,constpthread_attr_t*attr,
void*(*start_routine)(void*),void*arg);
線程等待函數:阻塞等待線程結束,結束後由主回收線程的資源
intpthread_join(pthread_tthread,void**retval);
線程分離函數:分離後,資源在線程結束時本身釋放,不有主線程回收
intpthread_detach(pthread_tthread);//這個函數和pthread_join兩者只能有一個被用
主動取消線程函數
int pthread_cancel(pthread_tthread);·取消是不是使能設置函數:默認狀況是使能
線程屬性設置函數
線程屬性有哪些:
a)綁定屬性:用戶線程和內核服務線程是否綁定(default:非綁定),cpu時間片的調度是面向內核線程實現的
b)分離屬性:線程結束時,線程資源由誰回收,設置了分離,就由本身釋放,未設置分離,資
源由等待線程(join函數等待)回收,(default:非分離),分離屬性也可由前
面的pthread_detach函數來設置
c)堆棧的地址和堆棧的大小:線程的堆棧其實就是函數的堆棧,是從進程的堆棧中刮分出來的,
默認狀況下,線程具體的堆棧地址由內核決定,堆棧大小默認1M,固然我也能夠認爲的更改它
d)線程的優先級:因爲線程是與它的生父進程(主線程)同樣統一地參與內核的
調度器的調度,因此存在着調度優先級的問題,默認狀況是他和生父進程有着一樣的優先級別
e)通常狀況下,咱們都採用默認設置便可
線程屬性設置函數
a)線程屬性初始化函數
intpthread_attr_init(pthread_attr_t*attr);
b)線程屬性刪除函數:刪除爲屬性設置,恢復內核原有默認的屬性設置,
防止永遠的穿改了默認的屬性設置
intpthread_attr_destroy(pthread_attr_t*attr);c)設置綁定函數
intpthread_attr_setscope(pthread_attr_t*attr,intscope);//設置intpthread_attr_getscope(pthread_attr_t*attr,int*scope);//獲取
d)設置分離屬性
intpthread_attr_setdetachstate(pthread_attr_t*attr,intdetachstate);//設置
intpthread_attr_getdetachstate(pthread_attr_t*attr,int*detachstate);//獲取
e)設置堆棧屬性
/*設置*/
intpthread_attr_setstack(pthread_attr_t*attr,void*stackaddr,size_tstacksize)
/*獲取*/intpthread_attr_getstack(pthread_attr_t*attr,void**stackaddr,size_t*stacksize)
f)設置優先級屬性
/*設置*/
intpthread_attr_setschedparam(pthread_attr_t*attr,conststructsched_param*param);
/*獲取*/
intpthread_attr_getschedparam(pthread_attr_t*attr,structsched_param*param);
設置互斥鎖相關的函數
互斥鎖初始化函數
intpthread_mutex_init(pthread_mutex_t*restrictmutex,constpthread_mutexattr_t*restrictattr);
互斥鎖直接初始化,只能初始化,不能賦值,由於pthread_mutex_t是結構體類型
pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;
互斥鎖銷燬函數
intpthread_mutex_destroy(pthread_mutex_t*mutex);
加鎖解鎖函數
阻塞解鎖:intpthread_mutex_lock(pthread_mutex_t*mutex);
非阻塞加鎖:intpthread_mutex_trylock(pthread_mutex_t*mutex);·解鎖:intpthread_mutex_unlock(pthread_mutex_t*mutex);
互斥鎖屬性設置函數
·互斥鎖屬性初始化和刪除
/*屬性初始化*/
intpthread_mutexattr_init(pthread_mutexattr_t*attr);/*互斥所屬性刪除:相似線程的屬性刪除*/
intpthread_mutexattr_destroy(pthread_mutexattr_t*attr);
互斥鎖類型設置和獲取
互斥鎖類型分類:
PTHREAD_MUTEX_DEFAULT:快速互斥鎖(或叫阻塞互斥鎖),默認此種鎖,統一把鎖,不能屢次加鎖,已經解開了的鎖也不能再次解鎖,這些都會出錯返回
PTHREAD_MUTEX_ERRORCHECK:檢錯互斥鎖,快速互斥鎖的費阻塞版本
PTHREAD_MUTEX_RECURSIVE:遞歸互斥鎖,同一把鎖可屢次枷鎖,每加一次鎖,鎖的鏈接計數加1,解鎖時的解鎖順序與加鎖順序相反,每解一次鏈接技術減1,加過多少次鎖,就必須接多少次
intpthread_mutexattr_settype(pthread_mutexattr_t*attr,inttype);//設置
intpthread_mutexattr_gettype(constpthread_mutexattr_t*restrictattr,int*restricttype);//獲取
設置線程信號量相關的函數
初始化函數
intsem_init(sem_t*sem,intpshared,unsignedintvalue);
刪除函數
intsem_destroy(sem_t*sem);
P操做:等資源
intsem_wait(sem_t*sem);//阻塞等待資源
intsem_trywait(sem_t*sem);//非阻塞等待資源/*可設置超時,阻塞超過必定時間,超時不在阻塞*/
intsem_timedwait(sem_t*sem,conststructtimespec*abs_timeout);
v操做:釋放資源
intsem_post(sem_t*sem);·信號量無屬性設置
條件變量設置
初始化和刪除函數/*初始化條件變量*/
intpthread_cond_init(pthread_cond_t*restrictcond,constpthread_condattr_t*restrictattr);
intpthread_cond_destroy(pthread_cond_t*cond);//刪除條件變量
pthread_cond_tcond=PTHREAD_COND_INITIALIZER;//直接變量初始化(不能賦值)
條件變量發送信號函數
/*喚醒所有由於該條件變量而休眠的線程*/
intpthread_cond_broadcast(pthread_cond_t*cond);/*喚醒其中一個由於該條件變量而休眠的線程*/intpthread_cond_signal(pthread_cond_t*cond);3)等待條件變量信號函數
/*可設置超時,等待超時,則超時返回*/
intpthread_cond_timedwait(pthread_cond_t*restrictcond,pthread_mutex_t*restrictmutex,conststructtimespec*restrictabstime);
/*一直等待,知道到等到喚醒信號*/
intpthread_cond_wait(pthread_cond_t*restrictcond,pthread_mutex_t*restrictmutex);·