Linux下多線程的應(yīng)用
時間:2017-01-05作者:華清遠(yuǎn)見
一、創(chuàng)建線程 函數(shù)簡介 phread_create是UNIX環(huán)境創(chuàng)建線程函數(shù) 頭文件 #include<pthread.h> 函數(shù)聲明
int pthread_create(pthread_t *restrict tidp 返回值 若成功則返回0,否則返回出錯編號 返回成功時,由tidp指向的內(nèi)存單元被設(shè)置為新創(chuàng)建線程的線程ID。attr參數(shù)用于制定各種不同的線程屬性。新創(chuàng)建的線程從start_rtn函數(shù)的地址開始運行,該函數(shù)只有一個空指針參數(shù)arg,如果需要像start_rtn函數(shù)傳遞的參數(shù)不止一個,那么需要把這些參數(shù)放到一個結(jié)構(gòu)體中,然后把這個結(jié)構(gòu)的地址作為arg的參數(shù)傳入。 linux下用c開發(fā)多線程程序,linux系統(tǒng)下的多線程遵循POSIX線程接口,稱為pthread。 參數(shù)
第一參數(shù)為指向線程標(biāo)識符的指針 另外,在編譯時注意加上-lpthread參數(shù),以調(diào)用靜態(tài)連接庫。因為pthread并非linux系統(tǒng)的默認(rèn)庫。 二、pthread_join 函數(shù)pthread_join用來等待一個線程的結(jié)束。函數(shù)原型為: extern int phread_join (pthead_t __th,void **_thread_return); 第一個參數(shù)為被等待的線程標(biāo)識符。第二個參數(shù)為一個用戶定義的指針,它可以用來存儲被等待線程的返會值。這個函數(shù)是一個線程阻塞的函數(shù),調(diào)用它的函數(shù)將一直等待到被等待的線程結(jié)束為止,當(dāng)函數(shù)返回時,被等待線程的資源被收回。如果執(zhí)行成功,將返回0,如果失敗則返回一個錯誤號。 在linux中,默認(rèn)情況下是在一個線程被創(chuàng)建后,必須使用此函數(shù)對創(chuàng)建的線程進(jìn)行資源回收,但是可以設(shè)置Threads attributes來設(shè)置當(dāng)一個線程結(jié)束時,直接回收此線程所占用的系統(tǒng)資源。 三、 互斥鎖pthread_mutex_t的使用 1.兩種方法創(chuàng)建互斥鎖,靜態(tài)方式和動態(tài)方式。 POXIX定義了一個PTHREAD_MUTEX_INITIALIZER來靜態(tài)初始化互斥鎖,方法如下:phread_mutex_t mutex=PTHREAD_MUTEX_INITALIZER;在LinuxThreads實現(xiàn)中,pthread_mutex_t是一個結(jié)構(gòu),而PTHREAD_MUTEX_INITIALIZER則是一個結(jié)構(gòu)常量。 動態(tài)方式是采用pthread_mutex_init()函數(shù)來初始化互斥鎖,API定義如下: int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr)其中mutexattr用于指定互斥屬性(見下),如果為NULL則使用缺省屬性。 pthread_mutex_destroy()用于注銷一個互斥鎖,API定義如下:int pthread_mutex_destory(pthread_mutex_t *mutex) 銷毀一個互斥鎖即意味著釋放它所占用的資源,且要求鎖當(dāng)前處于開發(fā)狀態(tài)。由于在linux中,互斥鎖并不占用任何資源,因此LinuxThreads中的pthread_mutex_destroy()除了檢查鎖狀態(tài)以外(鎖定狀態(tài)則返回EBUSY)沒有其他動作。 2.互斥鎖屬性 互斥鎖的屬性在創(chuàng)建鎖的時候指定,在LinuxThreads實現(xiàn)中僅有一個鎖類型屬性,不通的鎖類型試圖對一個已經(jīng)被鎖定的互斥鎖加鎖時表現(xiàn)不通。當(dāng)前(glibc 2.2.3,linuxthreads0.9)有四個值可供選擇: *PTHREAD_MUTEX_TIMED_NP,這是缺省值,也就是普通鎖。當(dāng)一個線程加鎖以后,其余請求鎖的線程將形成一個等待隊列,并在解鎖后按優(yōu)先級獲得鎖。這種鎖策略保證了資源分配的公平性。 *PTHREAD_MUTEX_RECURSIVE_NP,嵌套鎖,允許同一個線程對同一個鎖成功獲得多次,并通過多次unlock解鎖。如果是不同線程請求,則在加鎖線程解鎖時重新競爭。 *PTHREAD_MUTEX_ERRORCHECK_NP,檢錯鎖,如果同一個線程請求同一個鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP類型動作相同。這樣就保證當(dāng)步允許多次加鎖 時不會出現(xiàn)簡單情況下的死鎖。 *PTHREAD_MUTEX_ADAPTIVE_NP,適應(yīng)鎖,動作簡單的鎖類型,僅等待解鎖后重新競爭。 3.鎖操作 鎖操作主要包括加鎖pthread_mutex_lock()、解鎖pthread_mutex_unlock()和測試加鎖pthread_mutex_trylock()三個,不論哪種類型的鎖,都不可能被兩個不同的線程時得到,而必須等待解鎖。對于普通鎖和適應(yīng)鎖類型,解鎖者可以是同進(jìn)程內(nèi)任何線程;而檢錯鎖則必須由加鎖者解鎖才有效,否則EPERM;對于嵌套鎖,文檔和實現(xiàn)要求必須由加鎖者解鎖,但試驗結(jié)果表明并沒有這種限制,這個不同目前還沒有得到解釋。在同一進(jìn)程中的線程,如果加鎖后沒有解鎖,則任何其他線程都無法在獲得鎖。
int pthread_mutex_lock(pthread_mutex_t *mutex); phread_mutex_trylock()語義與pthread_mutex_lock()類似,不同的是在鎖已經(jīng)被占用時返回EBUSY而不是掛起等待。 四、使用條件變量提高效率 如果線程正在等待某個特定條件發(fā)生,它應(yīng)該如何處理這種情況?它可以重復(fù)對互斥對象鎖定和解鎖,每次都會檢查共享數(shù)據(jù)結(jié),以查找某個值。但這是在浪費時間和資源,而且這種繁忙查詢的效率非常低。解決這個問題的佳方法是使用pthread_cond_wait()調(diào)用來等待特殊條件發(fā)生。 條件變量是利用線程間共享的全局變量進(jìn)行同步的一種機(jī)制,主要包括連個動作:一個線程等待"條件變量的條件成立"而掛起;另一個線程使"條件成立"(給出條件成立信號)。為了防止競爭,條件變量的使用總是和一個互斥鎖結(jié)合在一起。 1.創(chuàng)建和注銷 條件變量和互斥鎖一樣,都有靜態(tài)、動態(tài)兩種創(chuàng)建方式,靜態(tài)方式使用PTHREAD_COND_INITIALIZER常量,如下: pthread_cond_t cond=PTHREAD_COND_INITIALIZER 動態(tài)方式調(diào)用pthread_cond_init()函數(shù),API定義如下: int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr); 盡管POSIX標(biāo)準(zhǔn)中為條件變量定義了屬性,但在LinuxThreads中沒有實現(xiàn),因此cond_attr值通常為NULL,且被忽略。 注銷一個條件變量需要調(diào)用pthread_cond_destroy(),只有在沒有線程在該條件變量上等待的時候才能注銷這個條件變量,否則返回EBUSY。因為Linux實現(xiàn)的條件變量沒有分配什么資源,所以注銷動作只包括檢查是否有等待線程。API定下如下: int pthread_cond_destroy(pthread_cond_t *cond); 2.等待和激發(fā)
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex) 等待條件有兩種方式:無條件等待pthread_cond_wait()和計時等待pthread_cond_timedwait(),其中計時等待如果在給定時刻前條件沒有滿足,則返回ETIMEOUT,結(jié)束等待,其中abstime以與time()系統(tǒng)調(diào)用相同意義的絕對時間形式出現(xiàn),0表示格林時間1970年1月1日0時0分0秒。 無論哪種等待方式,都必須和一個互斥鎖配合,以防止多個線程同時請求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的競爭條件。mutex互斥鎖必須是普通鎖(PTHREAD_MUTEX_TIMED_NP)或者適應(yīng)鎖(PTHREAD_MUTEX_ADAPTIVE_NP),且在調(diào)用pthread_cond_wait()前必須給本線程加鎖(pthread_mutex_lock()),而在更新條件等待隊列以前,mutex保持鎖定狀態(tài),并在線程掛起進(jìn)入等待前解鎖。在條件滿足從而離開pthread_cond_wait()之前,mutex將被重新加鎖,以與進(jìn)入pthread_cond_wait()前的加鎖動作對應(yīng)。 激發(fā)條件有兩種形式,pthread_cond_signal()激活一個等待該條件的線程,存在多個等待線程時按入隊順序激活其中一個;而pthread_cond_broadcast()則激活所有等待線程。
相關(guān)資訊
發(fā)表評論
|