引言:
北京時(shí)間:2023/7/7/9:58,耳機(jī)正在充電中,所以剛好讓我們先把引言寫一寫,昨天睡覺前聽了一會(huì)小說,聽小說的好處就在于,它可以讓你放下手機(jī),快速睡覺,并且還有一定的助眠效果,但是最近有點(diǎn)書荒,所以聽小說不是很積極,平時(shí)睡覺也就控制不住,昨天把很久以前看了一半沒看完的《龍族》給撿起來聽了一下,由于很久沒聽也沒看,支線和細(xì)節(jié)并不怎么清楚,所以挺起來比較沒勁,當(dāng)然當(dāng)初沒有把《龍族》追完,也是因?yàn)檫@本小說本質(zhì)不怎么對我的口味,但是這本小說一定是好文,從故事場景中的人物和細(xì)節(jié)描寫都能感覺的到,這本小說寫的非常好,在當(dāng)時(shí)那個(gè)年代,這本小說肯定是被大部分人奉為神作,當(dāng)時(shí)能寫出這種類型小說的作家頂級大佬無疑,不像現(xiàn)在,是人是鬼都能寫小說,懂的都懂!說真的從小說這方面,特別是玄幻小說,中國的歷史和文化有多牛,這里就不多說了,好了,話不多說,正式進(jìn)入該篇博客的主題,有關(guān)進(jìn)程控制相關(guān)的知識,當(dāng)然還有上篇博客剩余相關(guān)進(jìn)程優(yōu)缺點(diǎn)分析。
線程相關(guān)概念剩余知識
上篇博客由于時(shí)間和字?jǐn)?shù)問題,大致介紹完頁表映射問題,當(dāng)然也就是線程執(zhí)行過程之后,我們就草草結(jié)尾了,但是還有相關(guān)剩余知識沒有講解,在這進(jìn)行補(bǔ)充,大致就是關(guān)于頁表權(quán)限問題和線程優(yōu)缺點(diǎn)的分析,如下所述:
頁表權(quán)限問題
當(dāng)然上篇博客中有關(guān)頁表的講解,我們談到的只是頁表從虛擬地址映射到物理地址的一個(gè)具體過程,也就是如何通過一個(gè)實(shí)實(shí)在在的虛擬地址找到物理內(nèi)存中相應(yīng)的物理地址,所以還有相關(guān)拓展知識沒有深入講解,如權(quán)限問題,權(quán)限問題本質(zhì)也就是在找到這個(gè)物理地址之后,控制我們對該物理地址中數(shù)據(jù)的訪問,具體是只讀,還是讀寫,當(dāng)然這個(gè)問題在之前學(xué)習(xí)進(jìn)程信號時(shí),我們有一定的了解,也就是如果我們要對一個(gè)物理地址中的數(shù)據(jù)進(jìn)行讀寫操作,但是此時(shí)頁表檢測到我們只有讀權(quán)限,那么此時(shí)MMU(內(nèi)存管理單元)就會(huì)產(chǎn)生一個(gè)硬件異常信號,進(jìn)而終止對應(yīng)進(jìn)程非法寫入數(shù)據(jù)。同理,結(jié)合我們之前學(xué)習(xí)過的相關(guān)知識,明白,我們在編碼時(shí),如果使用指針定義了一個(gè)字符串常量,那么該常量是被存儲在虛擬地址空間上的常量區(qū)(只讀數(shù)據(jù)區(qū)),那么就規(guī)定好了,只讀數(shù)據(jù)區(qū)(常量區(qū))中的數(shù)據(jù)在進(jìn)行映射物理地址時(shí),只有讀權(quán)限,沒有寫權(quán)限,這也就是為什么我們在編碼時(shí),對應(yīng)指針指向的常量數(shù)據(jù)不允許被修改的本質(zhì)原因。
注意:
明白了上述知識,此時(shí)再來了解一下有關(guān)const的知識,本質(zhì)還是上述知識的變形,此時(shí)我們就知道,使用const關(guān)鍵字的本質(zhì)肯定是因?yàn)閷?yīng)的數(shù)據(jù)只有讀權(quán)限,沒有寫權(quán)限導(dǎo)致的,那么為什么會(huì)導(dǎo)致這個(gè)現(xiàn)象呢?本質(zhì)是因?yàn)榈骄幾g器檢測到某個(gè)數(shù)據(jù)被const修飾,屬于const數(shù)據(jù)時(shí),它就會(huì)對相應(yīng)的代碼進(jìn)行優(yōu)化(匯編過程進(jìn)行),讓對應(yīng)const類型的數(shù)據(jù)不在存儲在棧區(qū)上,而是將它存儲到只讀數(shù)據(jù)區(qū)(常量區(qū)),從而間接導(dǎo)致const修飾的數(shù)據(jù)在進(jìn)行頁表映射時(shí),只有讀權(quán)限,沒有寫權(quán)限。所以對于完整的頁表來說,它不僅具備虛擬地址和物理地址之間的索引關(guān)系,還包括了其它屬性(是否命中、權(quán)限等),入下圖所示:
線程優(yōu)缺點(diǎn)分析
搞定了上述有關(guān)頁表的所有知識,此時(shí)對于線程執(zhí)行過程,我們了然于胸,并且對于線程概念方面的知識,我們有了更深的理解,可以很好的理解下述線程概念:
一個(gè)程序中的一個(gè)執(zhí)行路線我們就叫做線程,更準(zhǔn)確的說,線程是一個(gè)進(jìn)程內(nèi)部的控制序列,一切進(jìn)程至少都有一個(gè)執(zhí)行線程,線程在進(jìn)程內(nèi)部運(yùn)行,本質(zhì)是在地址空間內(nèi)運(yùn)行,在Linux系統(tǒng)下,CPU執(zhí)行的進(jìn)程pcb都更加的輕量化,透過進(jìn)程地址空間,可以看到進(jìn)程的大部分資源,將進(jìn)程資源合理分配給每個(gè)執(zhí)行流,就形成了線程執(zhí)行流。
當(dāng)我們對上述有關(guān)線程概念都吃透之后,我們就來分析一下線程的相關(guān)優(yōu)點(diǎn)和缺點(diǎn),進(jìn)一步深入理解線程,當(dāng)然這部分知識講解完之后,我們就正式進(jìn)入到線程控制相關(guān)知識的學(xué)習(xí),如下所述:
1.線程優(yōu)點(diǎn)分析
-
創(chuàng)建一個(gè)新線程的代價(jià)要比創(chuàng)建一個(gè)新進(jìn)程小得多,這點(diǎn)是毋庸置疑的,無論是從線程共享進(jìn)程資源,還是操作系統(tǒng)維護(hù)進(jìn)程pcb來說,創(chuàng)建一個(gè)線程的代價(jià)都遠(yuǎn)小于創(chuàng)建進(jìn)程。
-
與進(jìn)程之間的切換相比,線程之間的切換需要操作系統(tǒng)做的工作要少很多,這點(diǎn)也是毋庸置疑的,同理線程由于共享進(jìn)程資源,所以在進(jìn)行線程切換時(shí),并不需要像進(jìn)程一樣,更換進(jìn)程pcb、地址空間、頁表、內(nèi)存或者是緩存中的數(shù)據(jù)。
-
線程占用的資源要比進(jìn)程少很多,無論是從Linux系統(tǒng)還是Windows系統(tǒng)來看,由于線程資源都是從進(jìn)程資源分配、共享,所以線程資源一定遠(yuǎn)少于進(jìn)程。
-
能充分利用多處理器的可并行數(shù)量,多核的好處就在于可以同時(shí)執(zhí)行不同的線程,當(dāng)然這里的線程并沒有特指是誰的線程,即可以是不同進(jìn)程的不同線程,也可以是同一進(jìn)程的不同線程。
-
在等待慢速I/O操作結(jié)束的同時(shí),程序可執(zhí)行其它計(jì)算任務(wù),也就相當(dāng)于你在使用某一款軟件時(shí),你可以一邊下載該軟件中的數(shù)據(jù)(慢),一邊對該軟件進(jìn)行別的操作,因?yàn)楫?dāng)你在進(jìn)行別的操作時(shí),該軟件就會(huì)創(chuàng)建其它的線程來幫你完成運(yùn)算,從而實(shí)現(xiàn)并發(fā)運(yùn)行。當(dāng)然對于該點(diǎn)來說,這種功能我們使用多進(jìn)程也能執(zhí)行,也就是創(chuàng)建不同的進(jìn)程,但是讓這些進(jìn)程看到同一份資源(軟件),然后對這份資源(軟件)進(jìn)行不同的操作,但是同理上述所說,創(chuàng)建進(jìn)程的消耗遠(yuǎn)大于線程,所以本質(zhì)使用多線程不使用多進(jìn)程還是為了提高效率。
-
計(jì)算密集型應(yīng)用,為了能在多處理器上運(yùn)行,將計(jì)算分解到多個(gè)線程中實(shí)現(xiàn),首先我們要明白什么叫計(jì)算密集型應(yīng)用,計(jì)算密集型應(yīng)用也就是需要大量的計(jì)算資源和處理能力,這類應(yīng)用一般涉及復(fù)雜的數(shù)學(xué)運(yùn)算、圖像/視屏處理等需要大量CPU計(jì)算的任務(wù),如加密解密,文件壓縮解壓。所以此時(shí)這種需要進(jìn)行大量計(jì)算的應(yīng)用就需要多線程多核并發(fā)共同完成。
-
I/O密集型應(yīng)用,為了提高性能,將I/O操作重疊,線程可以同時(shí)等待不同的I/O操作,同理,上述計(jì)算密集型涉及的是CPU的計(jì)算資源,那么I/O密集型涉及的就是大量的I/O操作,也就是對磁盤、網(wǎng)卡等進(jìn)行數(shù)據(jù)的讀取和寫入操作。這類應(yīng)用一般更加依賴于低延遲的存儲設(shè)備(磁盤)和高帶寬的網(wǎng)絡(luò)設(shè)備(網(wǎng)卡),如下載數(shù)據(jù),上傳數(shù)據(jù)。所以這類應(yīng)用也需要多線程多核并發(fā)完成。
注意:
都知道,當(dāng)我們想要讀數(shù)據(jù)(也就是進(jìn)行I/O),CPU只能從內(nèi)存中讀,但如果內(nèi)存中沒有,此時(shí)就會(huì)發(fā)生缺頁中斷,并且操作系統(tǒng)向磁盤申請數(shù)據(jù)加載到內(nèi)存的過程中,我們的線程由于沒有資源就會(huì)被操作系統(tǒng)掛起(進(jìn)程狀態(tài)中詳解),也就是等待對應(yīng)我需要的資源準(zhǔn)備就緒,只有當(dāng)對應(yīng)的數(shù)據(jù)從磁盤加載到內(nèi)存中之后,該線程才會(huì)從掛起狀態(tài)(等待)變?yōu)檫\(yùn)行狀態(tài),然后向后執(zhí)行,完成相應(yīng)操作。所以當(dāng)我們在進(jìn)行I/O操作時(shí),對應(yīng)進(jìn)行I/O操作的線程因?yàn)樯鲜鲈蚓鸵欢〞?huì)比計(jì)算密集型的線程更多,因?yàn)檫@樣就可以使等待效率提高,也就是讓更多的線程去等待,從而提高執(zhí)行效率。也就是對于計(jì)算密集型應(yīng)用來說,線程不是越多越好,對應(yīng)的線程一定要和CPU的個(gè)數(shù)掛鉤,只有這樣才能讓計(jì)算效率達(dá)到最高。
2.線程缺點(diǎn)分析
搞定了上述有關(guān)線程優(yōu)點(diǎn)以及線程使用策略相關(guān)的知識,此時(shí)我們來談?wù)劸€程的缺點(diǎn)吧!總的來說,大致可以分4個(gè)方面,性能損失、健壯性降低、缺乏訪問控制、編程難度提高
,如下分析所示:
-
性能損失:
當(dāng)然針對于這個(gè)場景,不僅僅是線程存在這個(gè)缺點(diǎn),進(jìn)程同理存在,也就是多核系統(tǒng)下,能夠同時(shí)運(yùn)行的線程是固定的,而系統(tǒng)中卻存在非常多的線程需要執(zhí)行,此時(shí)就需要通過不斷的去調(diào)度線程來達(dá)到程序被運(yùn)行起來,所以此時(shí)在不斷調(diào)度的過程中,就會(huì)導(dǎo)致性能損失,此時(shí)最好的解決方法就是控制線程個(gè)數(shù),減少調(diào)度的同時(shí),使效率達(dá)到最高。 -
健壯性降低:
如何理解這個(gè)健壯性降低呢?首先明白一個(gè)現(xiàn)象,也就是任何一個(gè)線程如果崩潰了,那么該線程對應(yīng)的進(jìn)程也會(huì)崩潰(終止),通過這個(gè)現(xiàn)象,此時(shí)我們就能明白,對某一個(gè)線程進(jìn)行編碼時(shí),需要更全面的考慮,考慮該線程是否會(huì)因?yàn)槟硞€(gè)錯(cuò)誤導(dǎo)致整個(gè)程序被終止,換句話說,也就是需要讓線程變得更加安全可靠,從而讓整個(gè)進(jìn)程得到保護(hù)。 -
缺乏訪問控制:
同理,因?yàn)槊總€(gè)線程共享同一份地址空間,那么就導(dǎo)致它們看到的所有資源(內(nèi)存上的數(shù)據(jù))都是一樣的,所以就會(huì)造成很多資源被不同的線程共同使用,類似于父進(jìn)程和子進(jìn)程的關(guān)系,唯一的區(qū)別就是子進(jìn)程不僅擁有自己的pcb,還擁有自己的地址空間,所以子進(jìn)程可以通過寫實(shí)拷貝等方法,更改地址空間中的共享數(shù)據(jù),而線程由于沒有地址空間,所以它并沒有辦法更改對應(yīng)的數(shù)據(jù),多線程一定是共享同一地址中的數(shù)據(jù),無論是否更改。所以最終就會(huì)導(dǎo)致地址空間中的數(shù)據(jù),缺乏訪問控制,也就是無論那個(gè)線程都可以訪問,那個(gè)線程都可以修改。 -
編程難度提高:
這個(gè)點(diǎn)就更好證明,簡單就從上述缺乏訪問控制來說,此時(shí)就會(huì)導(dǎo)致無論是那個(gè)線程都可以訪問同一個(gè)數(shù)據(jù),都可以修改同一個(gè)數(shù)據(jù),此時(shí)就導(dǎo)致數(shù)據(jù)容易被修改,從而引發(fā)健壯性問題,也就是線程崩潰,所以在進(jìn)行線程編碼時(shí),就需要注意,某個(gè)數(shù)據(jù)在使用前,是否被其它線程使用,其次再從健壯性來看,如果一個(gè)進(jìn)程出現(xiàn)問題,那么尋找問題(調(diào)式)就會(huì)變得非常困難,因?yàn)檫M(jìn)程崩潰,可以是任意一個(gè)線程導(dǎo)致。
多線程控制
明白了上述有關(guān)線程概念的知識,此時(shí)我們對線程的執(zhí)行過程和線程細(xì)節(jié)分析等知識都有了一定的認(rèn)識,最終明白,線程只是一個(gè)執(zhí)行流,它共享進(jìn)程資源的同時(shí),它也擁有自己的線程結(jié)構(gòu)體(LWP),擁有自己的數(shù)據(jù),如線程ID、寄存器組、??臻g、調(diào)度優(yōu)先級、信號屏蔽字、errno等,其中,當(dāng)我們談到寄存器組時(shí),我們就能意識到線程需要被調(diào)度,需要進(jìn)行上下文切換,因?yàn)橄鄳?yīng)CPU上的寄存器組就是用來保存被切換上下文的,而談到棧空間時(shí),我們就意識到線程由于共享地址空間,在并發(fā)執(zhí)行時(shí),為了避免互相干擾,就需要有??臻g來保存特定的臨時(shí)數(shù)據(jù)、臨時(shí)變量,因?yàn)橹挥羞@樣才可以使得每個(gè)線程可以在調(diào)用函數(shù)、局部變量等方面獨(dú)立于其他線程,從而實(shí)現(xiàn)并發(fā)獨(dú)立執(zhí)行。從寄存器組和??臻g我們充分體會(huì)到線程的臨時(shí)運(yùn)行特性和切換特性。
多線程接口實(shí)戰(zhàn)
搞定了上述知識,此時(shí)我們正式進(jìn)入多線程有關(guān)編碼方面的知識,重點(diǎn)在于有關(guān)線程接口、線程創(chuàng)建和線程控制等知識,首先是線程有關(guān)接口,談到接口,就離不開動(dòng)態(tài)庫,談到動(dòng)態(tài)庫,就離不開頭文件,所以當(dāng)我們想要使用系統(tǒng)調(diào)用接口去完成多線程的編碼,就需要使用相關(guān)的頭文件:pthread.h
,只有有了該頭文件,我們才能進(jìn)行與多線程有關(guān)的代碼編寫如下述代碼所示:
上述知識有兩個(gè)值得注意的地方,注意:
其一是有關(guān)動(dòng)態(tài)庫和頭文件相關(guān)的知識,在之前有關(guān)動(dòng)靜態(tài)庫的文章中,我們有進(jìn)行深入學(xué)習(xí),這里僅作復(fù)習(xí),明白,相應(yīng)的頭文件只是對應(yīng)動(dòng)態(tài)庫中對象、結(jié)構(gòu)體、函數(shù)調(diào)用接口的一個(gè)聲明,編譯器將對應(yīng)的頭文件進(jìn)行鏈接,從而生成可執(zhí)行程序,操作系統(tǒng)再根據(jù)可執(zhí)行程序,生成該程序的進(jìn)程地址空間,并且在該程序需要使用對應(yīng)動(dòng)態(tài)庫中的函數(shù)或者變量時(shí),將磁盤中對應(yīng)的動(dòng)態(tài)庫加載到內(nèi)存,當(dāng)然根據(jù)之前學(xué)過的缺頁中斷知識,這個(gè)過程肯定是通過缺頁中斷來完成,最終建立地址空間中共享區(qū)和物理內(nèi)存上動(dòng)態(tài)庫二進(jìn)制文件之間的映射關(guān)系。其二是有關(guān)操作系統(tǒng)不同的知識,當(dāng)然也就是Windows系統(tǒng)和Linux系統(tǒng)由于線程設(shè)計(jì)不同導(dǎo)致使用的不同,這點(diǎn)在之前有關(guān)線程概念方面我們詳細(xì)講解過,這里不再講解,也就是因?yàn)長inux系統(tǒng)沒有真正意義的線程,而是使用輕量級線程模擬的線程(LWP),所以,在Linux系統(tǒng)中,沒有提供直接創(chuàng)建線程的系統(tǒng)調(diào)用接口,同理,Linux系統(tǒng)只提供了創(chuàng)建輕量級進(jìn)程的接口。所以平時(shí)我們在Linux系統(tǒng)下,使用的線程創(chuàng)建接口,本質(zhì)是輕量級進(jìn)程創(chuàng)建接口,只不過是進(jìn)行了一定的封裝,實(shí)現(xiàn)貍貓換太子,讓我們以為創(chuàng)建的是線程而非是輕量級進(jìn)程。但值得注意的是,這個(gè)對輕量級線程接口的封裝,也就是對系統(tǒng)調(diào)用接口的封裝,一定是在用戶層,所以對應(yīng)Linux系統(tǒng)下創(chuàng)建線程的接口一定是在用戶級線程庫中,當(dāng)然也就是上述所說的pthread.h
頭文件。
1.pthread_create
明白了上述知識,此時(shí)我們正式來看看有關(guān)線程編碼相關(guān)的接口,首先第一個(gè)自然而然是有關(guān)線程創(chuàng)建接口,基本使用方式:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
可以看出,該接口的使用方式較為復(fù)雜,具體有待我們分析,首先明白pthread_t
本質(zhì)就是對一個(gè)無符號長整型(unsigned long
)進(jìn)行的重定義而已,類似于size_t
,所以此時(shí)就可以明白,其中第一個(gè)參數(shù)pthread_t *thread
表示就是該線程的ID,并且由于該參數(shù)是一個(gè)輸出型參數(shù),所以我們是可以直接獲取到該線程創(chuàng)建完成后,對應(yīng)的線程ID,具體如下代碼所示,這里我們先看看后面幾個(gè)參數(shù)表示的意思。其中第二個(gè)參數(shù),也就是const pthread_attr_t *attr
,這個(gè)參數(shù)表示的是線程的屬性(優(yōu)先級、狀態(tài)、??臻g等),也就是說,我們可以通過這個(gè)指針指向不同的結(jié)構(gòu)體,通過對這個(gè)結(jié)構(gòu)體的修改來修改一個(gè)線程的屬性,并且明白,如果這個(gè)參數(shù)如果給nullptr
,那么表示指向系統(tǒng)中默認(rèn)的結(jié)構(gòu)體,構(gòu)建出來的線程也就是一個(gè)操作系統(tǒng)規(guī)定好屬性的線程。然后是第三個(gè)參數(shù)void *(*start_routine) (void *)
,經(jīng)典的函數(shù)指針類型,返回值void*
,參數(shù)void*
,此時(shí)的start_routine
指針變量我們只需要給一個(gè)函數(shù)地址(函數(shù)名)就行,表示該線程需要執(zhí)行的一個(gè)接口或者是一段代碼。最后是第四個(gè)參數(shù)void *arg
,參數(shù)類型void*
,通過參數(shù)類型,可以猜測,該參數(shù)表示的就是第三個(gè)參數(shù)(函數(shù)指針類型)指向函數(shù)的參數(shù),也就是說,這個(gè)參數(shù)可以作為第三個(gè)參數(shù)指向函數(shù)的參數(shù),具體如下代碼所示:
同理,注意pthread庫文件并不是linux系統(tǒng)下的默認(rèn)動(dòng)態(tài)庫(不會(huì)自動(dòng)查找),所以在使用編譯器編譯鏈接,生成可執(zhí)行程序時(shí),需要指定鏈接pthread庫,指令:g++ -o $@ $^ -std=c++11 -lpthread
,并且知道,該庫是在lib64/libpthread.so
目錄下。
2.pthread_join
搞定了上述線程創(chuàng)建接口的使用,其余線程相關(guān)接口對于我們來說,并沒有那么重要,接下來我們馬上進(jìn)入線程控制相關(guān)知識的講解,pthread_join
接口基本使用方式:int pthread_join(pthread_t thread, void **retval);
同理,第一個(gè)參數(shù)表示對應(yīng)等待線程的線程ID。第二個(gè)參數(shù)*retval
表示一個(gè)指針,用于接收被等待線程的返回值,注意:因?yàn)樵搮?shù)的類型是void*
類型,所以需要進(jìn)行一個(gè)強(qiáng)制類型轉(zhuǎn)換,才能進(jìn)行對應(yīng)線程返回值的接收。明白,該接口就是類似于waitpid()
接口回收子進(jìn)程一般,但不同的是,等待原因不同,等待子進(jìn)程主要是為了防止內(nèi)存泄露等問題(僵尸進(jìn)程),而等待線程,主要是為了讓線程可以實(shí)現(xiàn)同步、協(xié)同運(yùn)行,保證線程之間的并發(fā)性,從而提高程序的執(zhí)行效率。當(dāng)然這兩個(gè)接口除了等待原因不同之外,在等待方式上也不同,其中waitpid()
接口默認(rèn)是非阻塞式等待,而pthread_join()
默認(rèn)是阻塞式等待,當(dāng)然,在使用對應(yīng)接口時(shí),具體是阻塞式等待還是非阻塞式等待,都是可以通過參數(shù)進(jìn)行控制的,具體使用方式如進(jìn)程控制代碼中所示,這里不進(jìn)行單獨(dú)演示。
3.pthread_exit
搞定了上述有關(guān)線程創(chuàng)建和線程等待的知識,此時(shí)對于多線程控制來說,只差線程終止相關(guān)接口,所以此時(shí)pthread_exit()
接口就是用于某個(gè)線程終止,因?yàn)橹挥挟?dāng)某個(gè)線程終止之后,我們才有資格對該線程進(jìn)行等待,基本使用方式:void pthread_exit(void *retval);
其中該接口中的參數(shù)同理pthread_join()
接口的第二個(gè)參數(shù),就是用于獲取該線程的退出狀態(tài),記錄線程退出信息,然后將該退出結(jié)果傳遞給等待該線程的其它線程(主線程),也就是pthread_join()
接口,注意:不能使用exit()
接口,因?yàn)?code>exit()接口是用于終止進(jìn)程,如果我們在任意一個(gè)線程中使用了exit()
接口,最終會(huì)導(dǎo)致整個(gè)進(jìn)程終止,導(dǎo)致該進(jìn)程中的所有線程被終止,出現(xiàn)大問題,所以在線程中,嚴(yán)禁使用exit()
接口。
4.pthread_cancel
同理,對于線程終止來說,還有一個(gè)關(guān)鍵接口,也就是 pthread_cancel,基本使用方式:int pthread_cancel(pthread_t thread);
這個(gè)接口較為簡單,表示的意思就是取消對應(yīng)ID的線程,這里不多做講解,具體如下述代碼所示。
多線程控制實(shí)戰(zhàn)
搞定了上述有關(guān)多線程接口相關(guān)的知識,線程創(chuàng)建、線程等待等知識我們就搞定的查不多了,接下來正式進(jìn)入該篇博客的重點(diǎn),有關(guān)多線程控制方面的知識,其中對于多線程控制來說,我們可以分為三個(gè)部分來學(xué)習(xí),線程創(chuàng)建、線程等待、線程終止,其中有關(guān)多線程創(chuàng)建,原理非常簡單,就是使用循環(huán)創(chuàng)建的方法,創(chuàng)建出多個(gè)線程,讓它們執(zhí)行同一份代碼(共享地址空間)而已,當(dāng)然也可以是不同的代碼。然后是線程等待,上述線程接口中我們簡單介紹了,這里不多做講解,最后是線程終止相關(guān)的知識,其中線程終止又可以分為多種不同的終止方法,如下所述:
1.線程執(zhí)行完畢return
2.直接調(diào)用pthread_exit接口
3.調(diào)用pthread_cancel接口
上述三種方法,就是讓一個(gè)線程終止,最后被等待的所有情況,當(dāng)然還有一種情況就是主線程終止導(dǎo)致線程終止,值得注意的是,線程只存在終止,并不存在退出異常等問題,因?yàn)槿绻粋€(gè)線程發(fā)生異常,整個(gè)進(jìn)程就會(huì)被終止,所以該線程是否正常已經(jīng)不重要的,不需要返回給進(jìn)程,因?yàn)檫M(jìn)程會(huì)被終止。文章來源:http://www.zghlxwxcb.cn/news/detail-552973.html
明白了上述有關(guān)線程終止方面的知識,此時(shí)有關(guān)線程控制等方面的知識我們就全部搞定啦!上述代碼本質(zhì)并沒有什么難度,重點(diǎn)就是有關(guān)線程創(chuàng)建、線程等待、線程終止方面的知識,至于像什么snprintf接口相關(guān)的使用,只是為了可以更好的區(qū)分每一個(gè)線程,給每一個(gè)線程取了一個(gè)名字而已,在該篇博客中,不做重點(diǎn)講解,有關(guān)線程控制相關(guān)的知識,該篇博客就到這了吧!See you!文章來源地址http://www.zghlxwxcb.cn/news/detail-552973.html
總結(jié):有關(guān)線程控制相關(guān)的知識,本質(zhì)就在于線程相關(guān)接口的理解和運(yùn)用,相比進(jìn)程控制來說,還是較為簡單的,學(xué)習(xí)成本不高。
到了這里,關(guān)于學(xué)習(xí)系統(tǒng)編程N(yùn)o.30【多線程控制實(shí)戰(zhàn)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!