一、雞肋:
1、線程理論基礎
(1)引入線程的原因:
Linux系統下,啟動一個新的進程,必須分配給它獨立的地址空間,建立眾多的資料表來維護它的程式碼片段、堆棧段,所以這種多任務的工作方式開銷非常大
(2)多線程的優點:
i、線程間切換的開銷遠小於進程間切換,據統計,差距在30倍左右
ii、線程間的通訊比進程間的通訊簡單。不同的進程都具有自己獨立的進程空間,他們之間的資料傳遞只能通過處理序間通訊的方式進行。這種方式費時費力;同一個進程中的不同線程,他們共用地址空間,共用資料空間,所以一個線程的資料可以直接為其他線程所用,這種方式快捷簡單。
2、LInux下的多線程
(1)Linux系統下的多線程遵循POSIX線程介面,稱為pthread。編寫Linux下的多線程程式時,需要使用標頭檔pthread.h,連結是需要使用庫libpthread.h
二、多線程程式設計
1、建立線程: int pthread_create(pthread_t * tidp,const pthread_attr_t * attr, void *(start_rtn)(void),void *arg);
(1)參數:
== tidp:線程id
==attr:線程屬性(通常為空白)
==start_rtn:線程要執行的函數
==arg: start_rtn 的參數
(2)注意:
用pthread_join()方法建立完線程後,線程是處於“就緒態”,不是“執行態”。所以,當前函數執行完該方法後會直接繼續執行下面的代碼,直到出現線程切換.
2、多線程程式的編譯:
因為pthread的庫不是linux系統的庫,所以在進行編譯的時候要加上 -lpthread,eg: #gcc filename -lpthread
3、線程等待: int pthread_join(pthread_t tid,void ** rval_ptr);
(1)引入原因:父進程等待子進程我們用wait()函數,那一個線程等待另一個線程,我們就可以用 pthread_join()函數。功能:阻塞當前的調用線程,直到指定的線程終止。
(2)參數:
== Tid : 等待退出的線程id
== Rval_ptr :被調用的線程退出後的傳回值會存放到rval_ptr中去
(3)注意:
main函數屬於進程,當main函數執行完後,整個進程就會執行完,此時,無論是否還有子線程在執行,都會退出。
4、線程標識(返回線程的ID):pthread_t pthread_self();
注意:這裡的線程的ID就等於進程的ID
5、清除
(1)線程終止有兩種情況
i、正常終止:線程主動調用pthread_exit或者從線程函數中return,都將使線程正常退出。
ii、非正常終止:是線程在其他線程的幹預下,或者由於自身運行出錯(比如訪問非法地址)而退出,這種退出方式是不可遇見的。
(2)不論是可遇見的線程終止還是異常終止,都會存在資源釋放的問題。所以,如何保證線程終止時能順利的釋放掉自己所佔用的資源,是一個必須要解決的問題。
(3) pthread_cleanup_push()到pthread_cleanup_pop之間的程式段(暫且叫做保護區代碼)中的終止動作(包括調用pthread_exit()和異常終止,不包括return)都將執行函數:pthead_cleanup_push()所指定的清理函數。
i、void pthread_cleanup_push(void (*rtn)(void *),void *arg );
參數:
a、rtn:清除函數
b、arg:清除函數要使用的參數
ii、void pthread_cleanup_pop(int execute);
功能:當保護區中的代碼沒有終止執行,pop函數就會把push函數指定的清除函數彈出清除棧
參數:
Execute參數用於判斷:當執行到 pthread_cleanup_pop()函數時,是否在彈出清理函數的同時執行該函數,
Execute,==非0:執行,==0:不執行。