摘要:多線程技術(shù)是個很龐大的課題,編程思想這本書英文版,以下簡稱中也用了頁介紹的多線程體系。一個線程歸屬于唯一的進(jìn)程,線程無法脫離進(jìn)程而存在。五線程內(nèi)數(shù)據(jù)線程的私有數(shù)據(jù)僅歸屬于一個線程,不在線程之間共享,例如,,。
多線程技術(shù)是個很龐大的課題,《Java編程思想》這本書(英文版,以下簡稱TIJ)中也用了136頁介紹Java的多線程體系。的確,Java語言發(fā)展到今天,多線程機制相比其他的語言從穩(wěn)定性,API的豐富度上絕對是數(shù)一數(shù)二的了。TIJ從Java語言的視角向我們展示了如何高效、正確地使用java api,但同時又不失普遍性,其中介紹的變量的原子性(atomicity)、可見性(visibility),多線程的資源競爭(resource contention),線程中斷(interruption),線程之間的協(xié)作(cooperation),多線程編程的一些實踐法則等對其他語言的程序員也具有很高的參考意義。
但限于篇幅,TIJ并未從操作系統(tǒng)的角度對線程作更多更深入的介紹,本系列文章試著由底向上,1)從操作系統(tǒng)的角度來理解線程,2)從JVM的層面來學(xué)習(xí)線程,3)借助其他語言的多線程機制來對比深入、熟練底掌握J(rèn)ava多線程編程。
本篇先從底層操作系統(tǒng)的視角重溫下線程相關(guān)的理論知識。
一、引入線程(thread)的目的
“同步”執(zhí)行多個任務(wù),提高資源使用效率,提升任務(wù)執(zhí)行速率。“同步”在單CPU環(huán)境下是個模擬并行的過程;在多CPU和多核CPU場景下,能夠真正并行執(zhí)行。單CPU場景下通過線程模擬多任務(wù)并行執(zhí)行;充分利用硬件資源,例如:讀取/寫入文件或網(wǎng)絡(luò),可由不同的CPU、不同的CPU核并行執(zhí)行。見圖一。
當(dāng)然,引入多線程后,相應(yīng)就要增加線程的調(diào)度(thread scheduling),上下文切換(context switching),額外的儲存空間(例如:線程棧,線程控制區(qū)等)。
二、進(jìn)程(process)的定義
進(jìn)程是程序(Program)在操作系統(tǒng)(Operation system)上的一次執(zhí)行,它有自己的虛擬地址空間。例如:運行一個java程序,打開IDE,操作系統(tǒng)都會為我們生成一個或多個進(jìn)程。
三、線程的定義
線程是進(jìn)程的一個子集,是進(jìn)程中的一段代碼。一個線程包括代碼段(code segment)、數(shù)據(jù)段(data segment)、寄存器(registers)、程序計算器(PC,program counter)、棧指針(SP,stack pointer)和線程控制區(qū)(TCB,Thread Control Block,存儲thread context,包括線程的PC,Register,SP等的數(shù)據(jù)結(jié)構(gòu)),上述數(shù)據(jù)結(jié)構(gòu)和進(jìn)程類似,因此線程也被稱為輕量級進(jìn)程(LWP,lightweight process)。
四、進(jìn)程與線程之間的關(guān)系
進(jìn)程必需要有一個線程,而且該線程是一個內(nèi)核線程(kernel thread)(因為kernel調(diào)度的往往是線程)。該線程也是進(jìn)程啟動時創(chuàng)建的第一個線程。而進(jìn)程的運行,實際上是進(jìn)程中的線程在運行,進(jìn)程只不過為線程提供了進(jìn)程地址空間(process address space),各種資源(file handler,socket等)。從這個角度來講進(jìn)程也是一個線程,一個為其他線程服務(wù)的線程。
TGID: thread group id也是進(jìn)程中第一個線程的id,即TID。利用fork或vfork或clone可以創(chuàng)建一個新的線程,如果不帶參數(shù)CLONE_THEAD,系統(tǒng)會創(chuàng)建一個新的線程,分配新的TID,這個TID也是新的TGID,而這個線程也是一個新的進(jìn)程。如果帶有參數(shù)CLONE_THEAD,則會在當(dāng)前進(jìn)程中創(chuàng)建一個新的線程,分配新的TID,而該線程的TGID和創(chuàng)建改線程的TGID保持一致。
一個線程歸屬于唯一的進(jìn)程,線程無法脫離進(jìn)程而存在。一個進(jìn)程中的多個線程共享相同的進(jìn)程空間,代碼段,數(shù)據(jù)段。見圖二。
五、線程內(nèi)數(shù)據(jù)
線程的私有數(shù)據(jù):僅歸屬于一個線程,不在線程之間共享,例如:PC,Stack,CP。
線程的共有數(shù)據(jù):程序代碼;全局變量;heap。
六、線程種類
內(nèi)核線程(kernel thread):顧名思義,內(nèi)核線程運行在kernel的進(jìn)程空間,由kernel負(fù)責(zé)創(chuàng)建,分配進(jìn)程空間,創(chuàng)建TCB;線程之間的調(diào)度,線程的銷毀等也都運行在內(nèi)核中。見圖三。
圖三:內(nèi)核線程(摘自:https://www.inf.ed.ac.uk/teac...)
用戶線程(user-level thread):用戶線程對kernel來說是透明的,也就是kernel并不知道用戶線程的存在。見圖四。
圖四:用戶線程(摘自:https://www.inf.ed.ac.uk/teac...)
由圖四可以看出用戶線程通過內(nèi)核線程來執(zhí)行任務(wù)。而內(nèi)核線程和用戶線程都有哪些關(guān)系?用戶線程如何映射到內(nèi)核線程?程序(program)和進(jìn)程關(guān)系又是怎樣的?在下一篇詳細(xì)介紹。
關(guān)注公眾號“碼農(nóng)走向藝術(shù)”獲取更多原創(chuàng)文章。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/77063.html
摘要:三種方式寫了下常見的查找和排序,思想的本質(zhì)是一致的,語言的運用有所不同罷了尷尬。 三種方式寫了下常見的查找和排序,思想的本質(zhì)是一致的,語言的運用有所不同罷了PS:尷尬。真的有必要隨時切換語言來編程,否則還想個半天.就跟前后臺的模板引擎一樣,花樣太多. JS 二分查找 /** * @param v Number 要查找的值 * @param a Array 數(shù)組(有序的:升序,譬如[2...
摘要:三種方式寫了下常見的查找和排序,思想的本質(zhì)是一致的,語言的運用有所不同罷了尷尬。 三種方式寫了下常見的查找和排序,思想的本質(zhì)是一致的,語言的運用有所不同罷了PS:尷尬。真的有必要隨時切換語言來編程,否則還想個半天.就跟前后臺的模板引擎一樣,花樣太多. JS 二分查找 /** * @param v Number 要查找的值 * @param a Array 數(shù)組(有序的:升序,譬如[2...
摘要:三種方式寫了下常見的查找和排序,思想的本質(zhì)是一致的,語言的運用有所不同罷了尷尬。 三種方式寫了下常見的查找和排序,思想的本質(zhì)是一致的,語言的運用有所不同罷了PS:尷尬。真的有必要隨時切換語言來編程,否則還想個半天.就跟前后臺的模板引擎一樣,花樣太多. JS 二分查找 /** * @param v Number 要查找的值 * @param a Array 數(shù)組(有序的:升序,譬如[2...
摘要:目標(biāo)線程由運行狀態(tài)轉(zhuǎn)換為就緒狀態(tài),也就是讓出執(zhí)行權(quán)限,讓其他線程得以優(yōu)先執(zhí)行,但其他線程能否優(yōu)先執(zhí)行時未知的。函數(shù)的官方解釋是意思是使調(diào)用該函數(shù)的線程讓出執(zhí)行時間給其他已就緒狀態(tài)的線程。 線程允許在同一個進(jìn)程中同時存在多個程序控制流,即通過線程可以實現(xiàn)同時處理多個任務(wù)的功能。線程會共享進(jìn)程范圍內(nèi)的資源,例如內(nèi)存句柄和文件句柄,但每個線程都有各自的程序計數(shù)器、棧以及局部變量。 多線程的實...
閱讀 1378·2021-09-26 09:55
閱讀 1917·2019-08-30 12:45
閱讀 1055·2019-08-29 11:20
閱讀 3555·2019-08-26 11:33
閱讀 3412·2019-08-26 10:55
閱讀 1685·2019-08-23 17:54
閱讀 2382·2019-08-23 15:55
閱讀 2341·2019-08-23 14:23