關(guān)于Linux多線程編程.doc_第1頁
關(guān)于Linux多線程編程.doc_第2頁
關(guān)于Linux多線程編程.doc_第3頁
關(guān)于Linux多線程編程.doc_第4頁
關(guān)于Linux多線程編程.doc_第5頁
已閱讀5頁,還剩1頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

關(guān)于Linux多線程編程Linux線程分為兩類,一是核心級(jí)支持線程,在核心級(jí)實(shí)現(xiàn)線程時(shí),線程的實(shí)現(xiàn)依賴于內(nèi)核,無論是在用戶進(jìn)程中的線程還是系統(tǒng)進(jìn)程中的線程,他們的創(chuàng)建、撤消、切換都由內(nèi)核實(shí)現(xiàn)。核心只有單線程進(jìn)程概念,而多線程進(jìn)程由與應(yīng)用程序連接的過程庫實(shí)現(xiàn)。另一類線程是用戶級(jí)線程,在Linux眾多的線程庫中,大部分實(shí)現(xiàn)的是用戶級(jí)線程。系統(tǒng)創(chuàng)建線程的順序如下:當(dāng)一個(gè)線程啟動(dòng)后,它會(huì)自動(dòng)創(chuàng)建一個(gè)線程即主線程(main thread)或者初始化線程(initial thread),然后就利用pthread_initialize()初始化系統(tǒng)管理線程并且啟動(dòng)線程機(jī)制。Linux線程編程基礎(chǔ)要?jiǎng)?chuàng)建一個(gè)多線程程序,必須加載pthread.h頭文件。要掌握多線程編程常用的幾個(gè)函數(shù):1、創(chuàng)建新線程函數(shù): pthread_create()2、掛起當(dāng)前線程函數(shù): pthread_join()3、線程注冊(cè)的清除處理函數(shù):pthread_exit()4、取消一個(gè)線程函數(shù): pthread_cancel()5、掛起當(dāng)前線程,直到滿足某種條件: pthread_cond_init多線程的同步1、互斥鎖互斥鎖用來保證一段時(shí)間內(nèi)只有一個(gè)線程在執(zhí)行一段代碼。當(dāng)在同一內(nèi)存空間運(yùn)行多個(gè)線程時(shí),為保證多個(gè)線程之間不相互破壞,要?jiǎng)?chuàng)建互斥量,如果一個(gè)線程已經(jīng)鎖定一個(gè)互斥量,第二個(gè)線程又試圖去鎖定這個(gè)互斥量,則第二個(gè)線程被掛起(不占用任何CPU資源),直到第一個(gè)線程解除對(duì)這個(gè)互斥量的鎖定為止。第二個(gè)線程將被喚醒并繼續(xù)執(zhí)行,同時(shí)鎖定這個(gè)互斥量。創(chuàng)建互斥量時(shí),必須首先聲明一個(gè)類型為pthread_mutex_t的變量,然后對(duì)其進(jìn)行初始化,結(jié)構(gòu)pthread_mutex_t為不公開的數(shù)據(jù)類型,其中包含一個(gè)系統(tǒng)分配的屬性對(duì)象。函數(shù)pthread_mutex_init用來生成一個(gè)互斥鎖。鎖定一個(gè)互斥量時(shí)使用函數(shù)pthread_mutex_lock(),它嘗試鎖定一個(gè)互斥量,如果該互斥量已經(jīng)被其它線程鎖定,該函數(shù)就把調(diào)用自己的線程掛起,一旦該互斥量解鎖,它將恢復(fù)運(yùn)行并鎖定該互斥量。這個(gè)線程在做完它的事情后,必須釋放這個(gè)互斥量,解除鎖定時(shí)使用函數(shù)pthread_mutex_unlock()。用完一個(gè)互斥量后必須銷毀它,這時(shí)沒有任何線程再需要它了,最后一個(gè)使用該互斥量的線程必須銷毀它,銷毀互斥量時(shí)使用函數(shù)pthread_mutex_destroy().2、條件變量互斥鎖一個(gè)明顯的缺點(diǎn)是它只有兩種狀態(tài):鎖定和非鎖定。在某種情況下,例如,在圖形用戶界面程序中,一個(gè)線程讀取用戶輸入,另一個(gè)線程處理圖形輸出,第三個(gè)線程發(fā)送請(qǐng)求到服務(wù)器并處理其響應(yīng),當(dāng)服務(wù)器的響應(yīng)到達(dá)時(shí),處理服務(wù)器的線程必須可以通知畫圖形的線程,畫圖形的線程把相應(yīng)的結(jié)果顯示給用戶。管理用戶輸入的線程必須總是能響應(yīng)用戶,例如,允許用戶取消正在由處理服務(wù)器的線程執(zhí)行的耗時(shí)的操作,這表明線程間必須可以互相傳遞信息,這時(shí)需要引入條件變量。條件變量是一種可以使線程(不消耗CPU)等待某些事件發(fā)生的機(jī)制。某些線程可能守候著一個(gè)條件變量,直到某個(gè)其它的線程給這個(gè)條件變量發(fā)送一個(gè)信號(hào),這時(shí)這些線程中的一個(gè)線程就會(huì)蘇醒,處理這個(gè)事件。也有可能利用對(duì)條件變量的廣播喚醒所有守侯著這個(gè)條件變量的線程。但條件變量不提供鎖定,所以它必須與一個(gè)互斥量同時(shí)使用,提供訪問這個(gè)環(huán)境變量時(shí)必要的鎖定。條件變量通過允許線程阻塞和等待另一個(gè)線程發(fā)送信號(hào)的方法彌補(bǔ)了互斥鎖的不足,它常和互斥鎖一起使用。使用時(shí),條件變量被用來阻塞一個(gè)線程,當(dāng)條件不滿足時(shí),線程往往解開相應(yīng)的互斥鎖,并等待條件發(fā)送變化。一旦其他的某個(gè)線程改變了條件變量,它將通知相應(yīng)的條件變量喚醒一個(gè)或多個(gè)正被此條件變量阻塞的線程。這些線程將重新鎖定互斥量,并重新測(cè)試條件是否滿足。一般來說,條件變量被用來進(jìn)行線程間的同步。下面通過一個(gè)例子來介紹條件變量:pthread_mutex_t count_mutex;pthread_cond_t cont_nonzero;unsigned int count;decrement_count() pthread_mutex_lock (&count_mutex); while(count= =0) pthread_cond_wait (&count_nonzero, & count_mutex); count=count 1; pthread_mutex_unlock (&count_mutex);increment_count() pthread_mutex_lock(&count_mutex); if(count= =0)pthead_cond_signal(&count_nonzero);count=count+1;pthread_mutex_unlock(&count_mutex);條件變量的結(jié)構(gòu)為pthread_cond_t,創(chuàng)建條件變量時(shí)必須首先聲明一個(gè)類型為pthread_cond_t的變量,然后對(duì)它進(jìn)行初始化。初始化可以如下所示:pthread_cond_t cond=PTHREAD_COND_INITIALIZER;但是,由于PTHREAD_COND_INITIALIZER是一個(gè)結(jié)構(gòu),所以只能在條件變量聲明時(shí)對(duì)它進(jìn)行初始化,在運(yùn)行時(shí)對(duì)條件變量進(jìn)行初始化,只能使用pthread_cond_init()函數(shù)。Int pthread_cond_init(pthread_cond_t * cond, pthread_condattr_t * cond_attr);Cond是一個(gè)指向結(jié)構(gòu)pthread_cond_t的指針,cond_attr是一個(gè)指向pthread_condattr_t的指針。結(jié)構(gòu)pthread_condattr_t是條件變量的屬性結(jié)構(gòu),和互斥鎖一樣,我們可以用它來設(shè)置條件是進(jìn)程內(nèi)可用還是進(jìn)程間可用,缺省值是PTHREAD_PROCESS_PRIVATE,即此條件變量被同一進(jìn)程內(nèi)的各個(gè)線程使用。函數(shù)pthread_cond_wait()使線程阻塞在一個(gè)條件變量上,解鎖時(shí)可以使用pthread_cond_signal()(只喚醒守侯著這個(gè)條件變量的一個(gè)線程)或使用pthread_cond_broadcast()函數(shù)(喚醒守侯著這個(gè)條件變量的所有線程)。如上例所示:iny rc=pthread_cond_signal(&count_nonzero);或者使用廣播函數(shù):iny rc=pthread_cond_broadcast(&count_nonzero);rc在成功時(shí)返回0,失敗時(shí)返回一個(gè)非0值,反映發(fā)生錯(cuò)誤的類型(EINVAL說明函數(shù)參數(shù)不是條件變量,ENOMEM說明系統(tǒng)沒有可用的內(nèi)存)。注意:發(fā)送信號(hào)成功不表明一定有線程被喚醒,可能這時(shí)候沒有線程在守侯該條件變量,并且這個(gè)信號(hào)會(huì)丟失,不會(huì)被使用。如果有新的線程開始守侯該條件變量,那么必須要有新的信號(hào)才能喚醒它。線程可以通過兩個(gè)函數(shù)pthread_cond_wait()和pthread_cond_timedwait()來守侯條件變量,這個(gè)兩個(gè)函數(shù)以一個(gè)條件變量和一個(gè)互斥量(應(yīng)該在調(diào)用之前鎖定)為參數(shù),解除對(duì)互斥量的鎖定,掛起線程的執(zhí)行,并處于等待狀態(tài),直到條件變量接收到信號(hào)。如果該線程被條件變量喚醒,守侯函數(shù)再次自動(dòng)鎖定互斥量,并開始執(zhí)行。這兩個(gè)函數(shù)的唯一區(qū)別是:pthread_cond_timedwait()允許用戶給定一個(gè)時(shí)間間隔,過了這個(gè)間隔,函數(shù)總是返回,返回值為ETIMEDOUT,表示在時(shí)間間隔之內(nèi)條件變量沒接收到信號(hào),阻塞也被解除。而如果沒有信號(hào)pthread_cond_wait(),將無限期等待下去。3、信號(hào)量如果我們編寫的程序中使用了多線程,那么在多用戶多進(jìn)程系統(tǒng)中,需要保證只有一個(gè)線程能夠?qū)δ硨戀Y源進(jìn)行排他性訪問(這些資源叫做臨界資源)。為防止多個(gè)程序訪問一個(gè)資源引發(fā)的問題,我們需要有一種方法生成并使用一個(gè)記號(hào),使得任意時(shí)刻只有一個(gè)線程擁有對(duì)該項(xiàng)資源的訪問權(quán)。信號(hào)量是一種特殊的變量,它只能取正整數(shù)值,對(duì)這些正整數(shù)只能采取兩種操作:P操作(代表等待,關(guān)操作)和V操作(代表信號(hào),開操作)。P/V操作的定義如下(假設(shè)我們有一個(gè)信號(hào)量sem):P(sem):如果sem的值大于0,則sem減1;如果sem的值為0,則掛起該線程。V(sem):如果有其它進(jìn)程因等待sem而被掛起,則讓它恢復(fù)執(zhí)行;如果沒有線程等待sem而被掛起,則sem加上1。 信號(hào)量的創(chuàng)建與打開要使用信號(hào)量,首先必須創(chuàng)建一個(gè)信號(hào)量。創(chuàng)建信號(hào)量的函數(shù)如下:# include # include # include int semget(key_t key,int nsems,int flag);函數(shù)semget()用于創(chuàng)建一個(gè)新的信號(hào)量集,或打開一個(gè)已存在的信號(hào)量集。其中,參數(shù)key表示所創(chuàng)建或打開的信號(hào)量集的鍵。參數(shù)nsems表示創(chuàng)建的信號(hào)量集中信號(hào)量的個(gè)數(shù),此參數(shù)只在創(chuàng)建一個(gè)新的信號(hào)量集時(shí)有效。參數(shù)flag表示調(diào)用函數(shù)的操作類型,也可用于設(shè)置信號(hào)量集的訪問權(quán)限,兩者通過邏輯或表示,它低端的九個(gè)位是該信號(hào)量的權(quán)限,可以與鍵值IPC_CREATE做按位或操作以創(chuàng)建一個(gè)新的信號(hào)量,即使在設(shè)置了IPC_CREATE后給出的是一個(gè)現(xiàn)有信號(hào)量的鍵字,也并不是一個(gè)錯(cuò)誤。如果IPC_CREATE標(biāo)識(shí)在函數(shù)里用不著,函數(shù)就會(huì)忽略它的作用。我們可以使用IPC_CREATE和IPC_EXCL標(biāo)識(shí)來創(chuàng)建一個(gè)獨(dú)一無二的新的信號(hào)量,如果該信號(hào)量已經(jīng)存在,則返回一個(gè)錯(cuò)誤。調(diào)用函數(shù)semget()的作用由參數(shù)key和flag決定,此函數(shù)調(diào)用成功時(shí),返回值為信號(hào)量的引用標(biāo)識(shí)符;調(diào)用失敗時(shí),返回值為-1。 對(duì)信號(hào)量的操作對(duì)信號(hào)量的操作使用如下函數(shù):# include # include # include int semop (int semid, struct sembuf semoparray , size_t nops ) ; 參數(shù)semid是信號(hào)量集的引用id,semoparray 是一個(gè)sembuf類型數(shù)組,sembuf結(jié)構(gòu)用于指定調(diào)用semop()函數(shù)所做的操作,數(shù)組semoparray 中元素的個(gè)數(shù)由nops決定。Sembuf的結(jié)構(gòu)如下:struct sembuf ushort sem_num; short sem_op; short sem_flag;其中,sem_num指定要操作的信號(hào)量。sem_op用于表示所執(zhí)行的操作。相應(yīng)取值和含義見下。sem_flag為操作標(biāo)記。與此函數(shù)相關(guān)的有IPC_NOWAIT和SEM_UNDO。1)sem_op0:表示線程對(duì)資源使用完畢,交回該資源。此時(shí)信號(hào)量集的semid_ds結(jié)構(gòu)的sem_base.semval將加上sem_op的值。如果此時(shí)設(shè)置了SEM_UNDO位,則信號(hào)量的調(diào)整值將減去sem_op的絕對(duì)值。2)sem_op=0:表示進(jìn)程要等待,直到sem_base.semval的值變?yōu)?。3)sem_op0:表示進(jìn)程希望使用資源。此時(shí)將比較sem_base.semval和sem_op的絕對(duì)值的大小。如果sem_base.semval大于等于sem_op的絕對(duì)值,表示資源足夠分配給該進(jìn)程,則sem_base.semval將減去sem_op的絕對(duì)值。如果此時(shí)設(shè)置了SEM_UNDO位,則信號(hào)量的調(diào)整值將加上sem_op的絕對(duì)值。如果sem_base.semval小于sem_op的絕對(duì)值,表示資源不足。如果設(shè)置了IPC_NOWAIT位,則函數(shù)出錯(cuò)返回,否則semid_ds結(jié)構(gòu)的sem_base.semval加1,進(jìn)程等待至sem_base.semval大于等于sem_op的絕對(duì)值或該信號(hào)量被刪除。 對(duì)信號(hào)量的控制對(duì)信號(hào)量的控制操作是通過semctl()來實(shí)現(xiàn)的,函數(shù)說明如下:# include # include # include int semctl (int semid, int semnum, int cmd, union semun arg);其中semid為信號(hào)量集的引用標(biāo)識(shí)符,semnum用于指定信號(hào)量集中某個(gè)特定的信號(hào)量,參

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論