LINUX環(huán)境高級編程-線程_第1頁
LINUX環(huán)境高級編程-線程_第2頁
LINUX環(huán)境高級編程-線程_第3頁
LINUX環(huán)境高級編程-線程_第4頁
LINUX環(huán)境高級編程-線程_第5頁
已閱讀5頁,還剩57頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、線程的概念線程的創(chuàng)建和操縱線程的同步代碼演示主要內(nèi)容POSIX線程(POSIX threads),簡稱Pthreads,是線程的POSIX標(biāo)準(zhǔn)。該標(biāo)準(zhǔn)定義了創(chuàng)建和操縱線程的一整套API,定義了一套C語言的類型、常量、函數(shù),以pthread.h頭文件和一個(gè)線程庫實(shí)現(xiàn)。POSIX線程具有很好的可移植性,使用pthreads編寫的代碼可運(yùn)行于類Unix操作系統(tǒng)(Unix、Linux、Mac OS X等)中,Windows操作系統(tǒng)也有其移植版pthreads-win32。3 3LinuxThreads項(xiàng)目最初將多線程的概念引入了 Linux,但是 LinuxThreads 并不完全遵守 POSIX 線

2、程標(biāo)準(zhǔn),并且存在設(shè)計(jì)的一些局限性;為了改進(jìn)Linux線程性能,IBM投資開發(fā) NGPT(Next-Generation POSIX Threads)項(xiàng)目,Red Hat主導(dǎo)本地化POSIX線程庫 (Native POSIX Thread Library,簡稱為NTPL)項(xiàng)目。大部分現(xiàn)代 Linux 發(fā)行版都預(yù)裝了 LinuxThreads 或 NPTL,要查看您的系統(tǒng)上正在使用的是哪個(gè)線程庫,請運(yùn)行下面的命令: $ getconf GNU_LIBPTHREAD_VERSION 這會(huì)產(chǎn)生類似于下面的輸出結(jié)果: NPTL 0.34 或者: linuxthreads-0.10程序(program):

3、是存放在磁盤文件中的可執(zhí)行文件。使用6個(gè)exec函數(shù)中的一個(gè)由內(nèi)核將程序讀入存儲(chǔ)器,并使其執(zhí)行。進(jìn)程(process):是資源管理的最小單位,是程序的執(zhí)行實(shí)例,是動(dòng)態(tài)過程。有些操作系統(tǒng)把任務(wù)和進(jìn)程同等看待,認(rèn)為任務(wù)是一個(gè)動(dòng)態(tài)過程,即執(zhí)行任務(wù)體的動(dòng)態(tài)過程。線程(thread):是程序執(zhí)行的最小單位,比進(jìn)程更小的、能獨(dú)立運(yùn)行和調(diào)度的基本單元,并以此來提高程序并行執(zhí)行的程度。5 5進(jìn)程存儲(chǔ)空間布局進(jìn)程管理著資源,如文件、內(nèi)存、CPU等;進(jìn)程的所有信息對該進(jìn)程的所有線程都是共享的,包括:可執(zhí)行的程序文本、程序的全局內(nèi)存、堆內(nèi)存、文件描述符等。線程獨(dú)有的包括:線程ID、寄存器值、棧、信號屏蔽字、errn

4、o值、線程私有數(shù)據(jù)。7 7一個(gè)進(jìn)程可以擁有多個(gè)線程;一個(gè)進(jìn)程至少需要一個(gè)線程作為它的指令執(zhí)行體;典型的UNIX進(jìn)程可以看成是只有一個(gè)線程的進(jìn)程。Linux系統(tǒng)下的多線程遵循POSIX線程接口,稱為pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,連接時(shí)需要使用庫libpthread.a。8 81、線程開銷更小。據(jù)統(tǒng)計(jì),總的說來,一個(gè)進(jìn)程的開銷大約是一個(gè)線程開銷的30倍左右。2、線程間通信更方便、快捷。同一進(jìn)程下的線程之間共享數(shù)據(jù)空間,所以一個(gè)線程的數(shù)據(jù)可以直接為其它線程所用,這不僅快捷,而且方便。3、使多CPU系統(tǒng)更加有效。操作系統(tǒng)會(huì)保證當(dāng)線程數(shù)不大于CPU數(shù)目時(shí)

5、,不同的線程運(yùn)行于不同的CPU上。4、改善程序結(jié)構(gòu)。一個(gè)既長又復(fù)雜的進(jìn)程可以考慮分為多個(gè)線程,成為幾個(gè)獨(dú)立或半獨(dú)立的運(yùn)行部分,這樣的程序會(huì)利于理解和修改。同進(jìn)程一樣,每個(gè)線程也有一個(gè)線程ID進(jìn)程ID在整個(gè)系統(tǒng)中是唯一的,但線程ID不同,線程ID只在它所屬的進(jìn)程環(huán)境中有效線程ID的類型是pthread_t,在Linux中的定義: 在/usr/include/bits/pthreadtypes.h中 typedef unsigned long int pthread_t;1010pthread_self函數(shù)可以使調(diào)用線程獲取自己的線程ID函數(shù)原型#includepthread_t pthread_

6、self();返回調(diào)用線程的線程ID1111Linux中使用整型表示線程ID,而其他系統(tǒng)則不一定FreeBSD 5.2.1、Mac OS X 10.3用一個(gè)指向pthread結(jié)構(gòu)的指針來表示pthread_t類型。為了移植性,在比較兩個(gè)線程ID是否相同時(shí),可以使用pthread_equal函數(shù)1212該函數(shù)用于比較兩個(gè)線程ID是否相同函數(shù)原型#includeint pthread_equal(pthread_t tid1, pthread_t tid2);若相等則返回非0值,否則返回01313進(jìn)程原語進(jìn)程原語線程原語線程原語描述描述forkpthread_create創(chuàng)建新的控制流exitpc

7、hread_exit從現(xiàn)有的控制流中退出waitpidpthread_join從控制流中得到退出狀態(tài)atexitpthread_cleanup_push注冊在退出控制流時(shí)調(diào)用的函數(shù)getpidpthread_self獲取控制流的IDabortpthread_cancel請求控制流的非正常退出pthread_create函數(shù)用于創(chuàng)建一個(gè)線程函數(shù)原型#includeint pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);參數(shù)與返回值 t

8、hread:當(dāng)pthread_create成功返回時(shí),該函數(shù)將線程ID存儲(chǔ)在thread指向的內(nèi)存區(qū)域中1515參數(shù)與返回值 attr:用于定制各種不同的線程屬性,將在后面部分討論。通??稍O(shè)為NULL,采用默認(rèn)線程屬性 start_routine:線程的入口函數(shù),即新創(chuàng)建的線程從該函數(shù)開始執(zhí)行。該函數(shù)只有一個(gè)參數(shù),即arg,返回一個(gè)指針 arg:作為start_routine的第一個(gè)參數(shù) 成功返回0,出錯(cuò)時(shí)返回各種錯(cuò)誤碼1616新創(chuàng)建的線程,將繼承調(diào)用pthread_create函數(shù)的線程的信號屏蔽字,但新線程的未決信號集將被清除。1717進(jìn)程中任一線程調(diào)用exit、_Exit、_exit,都

9、會(huì)導(dǎo)致整個(gè)進(jìn)程終止;當(dāng)線程接收到信號,若信號的處理動(dòng)作是終止進(jìn)程,則進(jìn)程將被終止(后面分析信號與線程的交互);如何只終止某個(gè)線程,而不終止整個(gè)進(jìn)程?1818單個(gè)線程的三種退出方式 線程從啟動(dòng)例程中返回,返回值是線程的退出碼 線程被同一進(jìn)程中的其他線程取消 線程調(diào)用pthread_exit函數(shù)1919該函數(shù)讓線程退出#includevoid pthread_exit(void *rval_ptr);參數(shù) rval_ptr:與線程的啟動(dòng)函數(shù)類似,該指針將傳遞給pthread_join函數(shù)2020該函數(shù)用于等待某個(gè)線程終止函數(shù)原型#includeint pthread_join(pthread_t

10、thread, void *rval_ptr);調(diào)用該函數(shù)的線程將一直阻塞,直到指定的線程調(diào)用pthread_exit、從啟動(dòng)例程中返回、被取消2121返回值與參數(shù) 成功返回0,否則返回錯(cuò)誤編號 thread:需要等待的線程ID rval_ptr: 若線程從啟動(dòng)例程返回,rval_ptr將包含返回碼 若線程由于pthread_exit終止,rval_ptr即pthread_exit的參數(shù) 若線程被取消,由rval_ptr指定的內(nèi)存單元就置為PTHREAD_CANCELED 若不關(guān)心線程返回值,可將該參數(shù)設(shè)置為NULL2222線程調(diào)用該函數(shù)可以取消同一進(jìn)程中的其他線程,即讓線程終止函數(shù)原型#in

11、cludeint pthread_cancel(pthread_t tid);參數(shù)與返回值 tid:需要取消的線程ID 成功返回0, 出錯(cuò)返回錯(cuò)誤編號2323在默認(rèn)情況下,pthread_cancel函數(shù)會(huì)使得線程ID等于tid的線程,如同其調(diào)用了參數(shù)為PTHREAD_CANCELED的pthread_exit線程可以選擇忽略取消方式或者控制取消方式,將在后面討論pthread_cancel并不等待線程終止,它僅僅是提出請求2424當(dāng)線程終止時(shí),可以調(diào)用自定義的線程清理處理函數(shù),進(jìn)行資源釋放等操作。類似于atexit函數(shù)。線程可以注冊多個(gè)清理處理函數(shù),這些函數(shù)被記錄在棧中,它們的執(zhí)行順序與它們

12、的注冊順序相反。線程清理處理函數(shù)的注冊:#includevoid pthread_cleanup_push(void (*rtn)(void *), void *arg);2525參數(shù) rtn:清理函數(shù),無返回值,一個(gè)類型為指針的參數(shù) arg:當(dāng)清理函數(shù)被調(diào)用時(shí),arg將傳遞給清理函數(shù)清理函數(shù)被調(diào)用的時(shí)機(jī) 調(diào)用pthread_exit時(shí) 響應(yīng)取消請求時(shí) 以非0參數(shù)調(diào)用pthread_cleanup_pop時(shí)2626pthread_cleanup_push必須和pthread_cleanup_pop成對出現(xiàn),而且出現(xiàn)的地方必須在同一個(gè)作用域內(nèi)函數(shù)原型 #include void pthread_

13、cleanup_pop(int execute);2727在默認(rèn)情況下,線程的終止?fàn)顟B(tài)會(huì)保存到對該線程調(diào)用pthread_join;pthread_detach函數(shù)可以使線程進(jìn)入分離狀態(tài);若線程已經(jīng)處于分離狀態(tài),線程的底層存儲(chǔ)資源可以在線程終止時(shí)立即被收回;當(dāng)線程被分離時(shí),并不能用pthread_join函數(shù)等待它的終止?fàn)顟B(tài),此時(shí)pthread_join返回EINVAL。2828函數(shù)原型#includeint pthread_detach(pthread_t tid);參數(shù)與返回值 tid:進(jìn)入分離狀態(tài)的線程的ID 成功返回0,出錯(cuò)返回錯(cuò)誤編號2929代碼演示線程同步的概念互斥量死鎖讀寫鎖條件

14、變量3131為什么需要同步 對同一個(gè)存儲(chǔ)單元,至少存在兩個(gè)執(zhí)行體,其一讀該單元,另一寫該單元,則需要同步,避免不一致性 在處理器架構(gòu)中,對內(nèi)存單元的修改,可能需要多個(gè)總線周期,因此讀操作和寫操作有可能交織在一起3232假設(shè)讀操作需要一個(gè)總線周期寫操作需要兩個(gè)總線周期線程B和線程A沖突3333使用鎖,以保證共享存儲(chǔ)一次只能被一個(gè)線程訪問說明獲取、釋放鎖的過程3434通常,對一個(gè)存儲(chǔ)單元的訪問,要經(jīng)歷三個(gè)步驟 將內(nèi)存單元中的數(shù)據(jù),讀入寄存器 對寄存器中的值進(jìn)行運(yùn)算 將寄存器中的值,寫回內(nèi)存單元無鎖時(shí)的情況3535可以通過使用pthread的互斥接口保護(hù)數(shù)據(jù),確保同一時(shí)間里只有一個(gè)線程訪問數(shù)據(jù)互斥量

15、mutex,本質(zhì)上就是一把鎖 在訪問共享資源前,對互斥量進(jìn)行加鎖 在訪問完成后釋放互斥量上的鎖 對互斥量進(jìn)行加鎖后,任何其他試圖再次對互斥量加鎖的線程將會(huì)被阻塞,直到鎖被釋放3636互斥量在使用前,必須要對互斥量進(jìn)行初始化函數(shù)原型#includeint pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);參數(shù)與返回值 mutex:即互斥量,類型是pthread_mutex_t 注意:mutex必須指向有效的內(nèi)存區(qū)域 attr:設(shè)置互斥量的屬性,通??刹捎媚J(rèn)屬性,即可將attr設(shè)為NULL。后面再

16、討論互斥量的屬性 成功返回0,出錯(cuò)返回錯(cuò)誤碼3737互斥量在使用完畢后,必須要對互斥量進(jìn)行銷毀,以釋放資源函數(shù)原型#includeint pthread_mutex_destroy(pthread_mutex_t *mutex);參數(shù)與返回值 mutex:即互斥量 成功返回0,出錯(cuò)返回錯(cuò)誤碼3838在對共享資源訪問之前和訪問之后,需要對互斥量進(jìn)行加鎖和解鎖操作函數(shù)原型#includeint pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);3939當(dāng)使用pthr

17、ead_mutex_lock時(shí),若已被加鎖,則調(diào)用線程將被阻塞。有沒有辦法讓線程不阻塞,即實(shí)現(xiàn)非阻塞的語義函數(shù)原型#includeint pthread_mutex_trylock(pthread_mutex_t *mutex);調(diào)用該函數(shù)時(shí),若互斥量未加鎖,則鎖住該互斥量,返回0;若互斥量已加鎖,則函數(shù)直接返回失敗,即EBUSY4040定義一個(gè)互斥量pthread_mutex_t調(diào)用pthread_mutex_init初始化互斥量調(diào)用pthread_mutex_lock或者pthread_mutex_tryplock對互斥量進(jìn)行加鎖操作調(diào)用pthread_mutex_unlock對互斥量解鎖

18、調(diào)用pthread_mutex_destroy銷毀互斥量4141若線程試圖對同一個(gè)互斥量加鎖兩次,那么它自身就會(huì)陷入死鎖狀態(tài)多個(gè)互斥量時(shí),可能出現(xiàn)死鎖 一個(gè)線程鎖住互斥量A,等等待互斥量B解鎖 另一個(gè)線程鎖住B,而等待A 避免方法: 按照固定的順序?qū)コ饬窟M(jìn)行加鎖操作,如先鎖A,再鎖B 當(dāng)對互斥量加鎖順序的控制很困難時(shí),可以先使用pthread_mutex_trylock,若不能獲取鎖,可釋放已占有的鎖4242讀寫鎖與互斥量類似,不過讀寫鎖允許更高的并行性互斥量只有兩種狀態(tài):鎖住、不加鎖讀寫鎖三種狀態(tài) 讀模式下加鎖狀態(tài) 寫模式下加鎖狀態(tài) 不加鎖狀態(tài)一次只有一個(gè)線程可以占有寫模式的讀寫鎖、但多個(gè)

19、線程可以同時(shí)占用讀模式的讀寫鎖4343當(dāng)讀寫鎖是寫加鎖狀態(tài)時(shí),解鎖之前,所有試圖對這個(gè)鎖加鎖的線程都會(huì)被阻塞當(dāng)讀寫鎖是讀加鎖狀態(tài)時(shí),所有試圖以讀模式對它進(jìn)行加鎖的線程,都可以得到訪問權(quán),但以寫模式進(jìn)行加鎖時(shí),它必須阻塞直到所有的線程釋放讀鎖4444與互斥量一樣,讀寫鎖在使用之前,必須要初始化;使用之后,必須要銷毀函數(shù)原型int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);參數(shù)

20、 rwlock:讀寫鎖 attr:讀寫鎖屬性,若用默認(rèn)屬性,可設(shè)置為NULL。將在后面討論相關(guān)屬性4545該函數(shù)用于鎖定讀鎖函數(shù)原型#includeint pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);參數(shù)與返回值 rwlock:讀寫鎖 成功返回0,否則返回錯(cuò)誤編號4646該函數(shù)用于鎖定寫鎖函數(shù)原型#includeint pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);參數(shù)與返回值 rwlock:讀寫鎖 成功返回0,否則返回錯(cuò)誤編號4747該函數(shù)用于解除讀鎖或者寫鎖函數(shù)原型#includeint

21、pthread_rwlock_unlock(pthread_rwlock_t *rwlock);參數(shù)與返回值 rwlock:讀寫鎖 成功返回0,否則返回錯(cuò)誤編號4848該兩個(gè)函數(shù)分別用于嘗試獲取讀鎖、寫鎖函數(shù)原型#includeint pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);參數(shù)與返回值 rwlock:讀寫鎖 成功返回0,否則返回錯(cuò)誤編號??梢垣@取鎖時(shí),函數(shù)返回0;否則返回錯(cuò)誤EBUSY4949現(xiàn)有一需求,線程A先執(zhí)行某操作

22、后,線程B才能執(zhí)行另一操作,該如何實(shí)現(xiàn)?條件變量與互斥量一起使用時(shí),允許線程以無競爭的方式等待特定條件的發(fā)生與互斥量類似,條件變量也需要初始化和銷毀5050函數(shù)原型#includeint pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);int pthread_cond_destroy(pthread_cond_t * cond);參數(shù)和返回值 cond:條件變量 attr:條件變量屬性,若為NULL,則使用默認(rèn)屬性 成功返回0,出錯(cuò)返回錯(cuò)誤編號5151pthread_cond_wait函數(shù)將使調(diào)用線程進(jìn)入阻塞狀

23、態(tài),直到條件為真函數(shù)原型#includeint pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);參數(shù)與返回值 cond:條件變量 mutex:互斥量 成功返回0,否則返回錯(cuò)誤編號 5252為什么pthread_cond_wait需要互斥量 在調(diào)用pthread_cond_wait前,需要使互斥量處于鎖住狀態(tài) 這樣pthread_cond_wait函數(shù),可以以原子的方式,將調(diào)用線程放到等待條件的線程列表上pthread_cond_wait函數(shù)的特殊操作 在線程阻塞前,調(diào)用pthread_mutex_unlock 在線

24、程喚醒后,條用pthread_mutex_lock5353等待線程的操作順序 調(diào)用pthread_mutex_lock 調(diào)用pthread_cond_wait 調(diào)用pthread_mutex_unlock5454pthread_cond_signal和pthread_cond_broadcast可以通知等待的線程,條件已經(jīng)滿足。pthread_cond_signal喚醒某一個(gè)等待該條件的線程pthread_cond_broadcast喚醒等待該條件的所有線程5555函數(shù)原型#includeint pthread_cond_signal(pthread_cond_t *cond);int pthread_cond_broadcast(pthread_cond_t *);參數(shù)與返回值 cond:條件變量 成功返回0,否則返回錯(cuò)誤編號5656等待線程 調(diào)用pthread_

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論