linux應用之線程編程
線程概述[/b]
進程是系統中程序執行和資源分配的基本單位。每個進程有自己的數據段、代碼段和堆棧段。
線程通常叫做輕型的進程。線程是在共享內存空間中並發執行的多道執行路徑,他們共享一個進程的資源。
線程的共性
同一個進程中的線程都有共性:多個線程將共享同一個進程虛擬空間。
線程共享的環境包括:進程代碼段、進程的公有數據(利用這些共享的數據,線程 很容易的實現相互之間的通訊)、進程打開的文件描述符、信號的處理器、進程的當前目錄和進程用戶ID與進程組ID。
線程的個性
線程ID–每個線程都有自己的線程ID,這個ID在本進程中是唯一的
寄存器組的值–一個線程切換到另一個線程上時,必須將原有的線程的寄存器集合的狀態保存,以便將來該線程在被重新切換到時能得以恢復
線程的堆棧–線程必須擁有自己的函數堆棧,使得函數調用可以正常執行,不受其他線程的影響
錯誤返回碼–不同線程擁有自己的錯誤返回碼變量
線程的信號屏蔽碼–線程的信號屏蔽碼應該由線程自己管理,但所有的線程都共享同樣的信號處理器
線程的優先級–由於線程需要像進程那樣能夠被調度,那麼就必須要有可供調度使用的參數,這個參數就是線程的優先級
使用多線程的理由之一是和進程相比,它是一種非常 " 節儉 " 的多任務操作方式。
使用多線程的理由之二是線程間方便的通信機制。
使用多線程的優點:
提高應用程序響應。當一個操作耗時很長時,整個系統都會等待這個操作,多線程技術會將耗時長的操作( time cons uming )置於一個新的線程。
使多 CP U 系統更加有效。操作系統會保證當線程數不大於 CPU數目時,不同的線程運行於不同的 CP U 上。
改善程序結構。一個既長又復雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分。
進程線程對比:
pthread 定義為 C 語言類型和過程 ( 函數 ) 集,包含在頭文件pthread.h
和 pthread 庫中。
大部分 pthreads 函數成功執行返回 0 ,出錯返回非 0 值。
常見模型:
管理者/工作者:管理者 ( 單個線程 ) 分配任務給多個工作者( 多個線程 ) ,可采用工作池方式。
生產線:一任務分為許多順序子任務,一個子任務完成後進入下一子任務。各個子任務采用線程完成。如同汽車生產線。
對等:類似於管理者 / 工作者,只是管理者分配完任務後也加入任務中去。
pthreads API 主要包含4部分的內容:
1. 線程管理:指直接使用線程的例程,如創建、分離、加入線程等,也包括設置/查詢線程屬性等例程。
2. 互斥:處理線程同步的例程。包括創建、 刪除、 鎖定、 解鎖、互斥量等。
3. 條件變量:線程間通過共享互斥量通訊的例程。包括在指定的條件變量上創建、刪除、發信號、等待等例程。
4. 同步化:管理讀寫鎖和路障的例程。
命名規程
前綴
說明
pthread_
線程本身及各種子例程
pthread_attr_
線程屬性對象
pthread_mutex_
互斥量
pthread_mutexattr_
互斥屬性對象
pthread_cond_
條件變量
pthread_condattr_
條件屬性對象
pthread_key_
線程特定的關鍵數據
pthread_rwlock_
讀寫鎖
pthread_barrier_
同步化路障
線程函數:
創建和終止線程
int pthread _create(pthread _t * thread , const pthread_attr_t
* attr , void *(*start_routine)(void *), void
* arg );
void pthread_exit( void * status);
int pthread_cancel (pthread_t thread);
用 pthread_create() 來創建線程,在線程的處理函數中,可以顯示的調用
pthread_exit()結束線程執行,也可以不調用pthread_exit() ,而只是讓線程處理程序返回。線程也可以使用 pthread_cancel() 函數終止其他線程的執行。
結合和分離線程
int pthread_join( pthread_t threadid , void ** status );
int pthread_detach(pthread_t threadid);
等待線程結束
pthread_join()函數會掛起創建線程的線程的執行,直到等待到想要等待的子線程。
線程的分離
主線程創建子線程,當子線程本身自己有自我回收內存資源的能力時可以和主線程分離。
其它一些線程管理函數
pthread_t pthread_self (void);
int pthread_equal (pthread_t thread1, pthread_t thread2);
int pthread_once(pthread_once_t *once_control,void
(*init_routine)(void));
用 pthread_self() 來獲得當前線程的標識符。用
pthread_equal() 來判斷兩個進程標識符是否相等,相等返回 0 ,否則非 0 值。當線程初始化只需要執行一次時,使用 pthread_once()來控制初始化例程只被執行一次。
進程線程函數對比:
進程
線程
描述
fork
pthread_create
創建新的控制流
exit
pthread_exit
從控制流中退出
waitpid
pthread_join
獲取控制流退出狀態
atexit
pthread_cancel_push
注冊控制流退出時要執行
的函數
getpid
pthread_self
獲取控制流 ID
abort
pthread_cancel
控制流非正常退出
Pthreads API-屬性對象:
線程具有屬性,用 pthread_attr_t 表示,通過設置屬性,可以指定一種不同於缺省行為的行為。使用 pthread_create() 創建線程時,或初始化同步變量時,可以指定屬性對象 (
通常使用缺省值就足夠了 )。在進程退出時需要銷毀屬性對象。屬性對象是不透明的,而且不能通過賦值直接進行修改。系統提供了一組函數,用於初始化、配置和銷毀每種對象類型。
初始化和配置屬性後,屬性便具有進程范圍的作用域。使用屬性時最好的方法即是在程序執行早期一次配置好所有必需的狀態規范。然後,根據需要引用相應的屬性對象。
使用屬性對象具有兩個主要優點。
1. 使用屬性對象可增加代碼可移植性。
2. 應用程序中的狀態規范已被簡化
int pthread_attr_init( pthread_attr_t *tattr);
int pthread_attr_destroy(pthread_attr_t *tattr) ;
int pthread_attr_s etdetachstate( pthread_attr_t *tattr,int
detach state); // 設置分離狀態
int pthread_attr_getdetachstate(const pthread_attr_t *tattr ,int
*detach state); // 獲取分離狀態
P THREAD_CREATE_ DETACHE D
P THREAD_CREATE_JO I NABL E
int p
thread_attr_setguard size(pthread_attr_t *attr ,size_t guard size); // 設置棧溢出保護區大小
int pthread_attr_getguardsize(const pthread_attr_t *attr ,size_t
*guardsize); // 獲取棧溢出保護區大小
int pthread_attr_setstacksize(pthread_attr_t *tattr ,size_t size);
// 設置棧大小
int pthread_attr_getstacksize(pthread_attr_t *tattr ,size_t *size);
// 獲取棧大小
size 包含新線程使用的棧的字節數。如果 size 為零, 則使用缺省大小。在大多數情況下,零值最適合。 PTHREAD_STACK_MIN是啟動線程所需的棧空間量。此棧空間沒有考慮執行應用程序代碼所需的線程例程要求。
同步對象是內存中的變量,可以按照與訪問數據完全相同的方式對其進行訪問。不同進程中的線程可以通過放在由線程控制的共享內存中的同步對象互相通信。盡管不同進程中的線程通常互不可見,但這些線程仍可以互相通信。
同步對象還可以放在文件中。同步對象可以比創建它的進程具有更長的生命周期。
同步對象具有以下可用類型:
互斥鎖
條件變量
讀寫鎖
信號