一硫朦、進(jìn)程和線程
1.操作系統(tǒng)苟跪、進(jìn)程状共、線程的關(guān)系
操作系統(tǒng)是包含多個(gè)進(jìn)程的容器,而每個(gè)進(jìn)程又是容納多個(gè)線程的容器尘应。
2.Oracle 官方定義
- 進(jìn)程:使用 fork(2) 系統(tǒng)調(diào)用創(chuàng)建的UNIX 環(huán)境(例如文件描述符惶凝,用戶 ID 等),它被設(shè)置為運(yùn)行程序犬钢。
- 線程:在進(jìn)程上下文執(zhí)行的一系列指令苍鲜。
3.什么是進(jìn)程
- 進(jìn)程(Process)是程序的運(yùn)行實(shí)例。
- 進(jìn)程是程序向操作系統(tǒng)申請(qǐng)資源(如內(nèi)存空間和文件句柄)的基本單位玷犹。
在用戶下達(dá)運(yùn)行程序的命令后混滔,就會(huì)產(chǎn)生進(jìn)程,任務(wù)管理器中的每一個(gè)應(yīng)用都是一個(gè)進(jìn)程歹颓。谷歌瀏覽器的每個(gè)標(biāo)簽頁(yè)和插件都是一個(gè)進(jìn)程坯屿。
4.什么是線程
線程是操作系統(tǒng)能夠進(jìn)行資源調(diào)度的最小單位,它被包含在進(jìn)程之中巍扛,是進(jìn)程中的實(shí)際運(yùn)作單位领跛,每個(gè)線程執(zhí)行的都是進(jìn)程代碼的某個(gè)片段,特定的線程總是在執(zhí)行特定的任務(wù)撤奸。
5.進(jìn)程和線程的關(guān)系
5.1 起源不同
先有進(jìn)程吠昭,后有線程鹅经。進(jìn)程由于資源利用率、公平性和便利性誕生怎诫。處理器的速度往往比外設(shè)的速度快(鍵盤、鼠標(biāo)等)贷痪,為了提高 CPU 的利用率幻妓,誕生了線程,目的就是為了提高程序的執(zhí)行效率劫拢。
5.2 概念不同
- 進(jìn)程是資源分配的最小單位肉津。
- 線程是程序執(zhí)行的最小單位(線程是操作系統(tǒng)能夠進(jìn)行資源調(diào)度的最小單位,同個(gè)進(jìn)程中的線程也可以被同時(shí)調(diào)度到多個(gè) CPU 上運(yùn)行)舱沧,線程也被稱為輕量級(jí)進(jìn)程妹沙。
5.3 內(nèi)存共享方式不同
- 默認(rèn)情況下,進(jìn)程的內(nèi)存無(wú)法與其他進(jìn)程共享(進(jìn)程間通信通過(guò) IPC 進(jìn)行)熟吏。
- 線程共享由操作系統(tǒng)分配給其父進(jìn)程的內(nèi)存塊距糖。
5.4 擁有資源不同
- 操作系統(tǒng)為各個(gè)獨(dú)立執(zhí)行的進(jìn)程分配各種資源,包括內(nèi)存牵寺,文件句柄以及安全證書等悍引。
- 線程會(huì)共享進(jìn)程范圍內(nèi)的資源,例如內(nèi)存句柄帽氓、文件句柄趣斤、進(jìn)程用戶 ID 以及進(jìn)程組 ID 等。每個(gè)線程也有各自獨(dú)立的資源黎休,例如線程 ID浓领、程序計(jì)數(shù)器、棧以及局部變量等势腮。
5.5 數(shù)量不同
一個(gè)程序至少擁有一個(gè)進(jìn)程联贩,一個(gè)進(jìn)程至少擁有一個(gè)線程。
5.6 開(kāi)銷不同
- 線程的創(chuàng)建捎拯、終止時(shí)間比進(jìn)程短撑蒜。
- 同一進(jìn)程內(nèi)的線程切換時(shí)間比進(jìn)程短。
- 同一進(jìn)程的各個(gè)線程間共享內(nèi)存和文件資源玄渗,可以不通過(guò)內(nèi)核進(jìn)行通信座菠。
5.7 生命周期類似
進(jìn)程和線程都包含就緒、運(yùn)行藤树、等待狀態(tài)浴滴。
6.Java 和多線程的關(guān)系
Java 在設(shè)計(jì)之初就支持了多線程,而且 Java 中的線程會(huì)一對(duì)一映射到操作系統(tǒng)的內(nèi)核線程中(實(shí)際的線程數(shù)量岁钓,不是虛擬線程)升略。除了我們啟動(dòng)的線程微王,還包括 JVM 自啟動(dòng)線程。
二品嚣、多線程
1.什么是多線程
1.1 概念
多線程是指單個(gè)進(jìn)程中運(yùn)行多個(gè)線程炕倘,如果一個(gè)程序允許運(yùn)行兩個(gè)或以上的線程,那么它就是多線程程序翰撑。
1.2 例子
- 房間的例子
- 客廳:公共空間
- 廁所:鎖
- 獨(dú)立房間:線程共享空間
- 打掃衛(wèi)生:線程合作
- 火鍋的例子
- 大火鍋一個(gè)人吃:?jiǎn)芜M(jìn)程單線程
- 大火鍋多個(gè)人吃:?jiǎn)芜M(jìn)程多線程
2. 使用多線程的原因
2.1 發(fā)揮多核處理器的強(qiáng)大能力
- 充分發(fā)揮多核 CPU 的優(yōu)勢(shì)罩旋,提高處理器速度。
- 避免無(wú)效等待(進(jìn)行 I/O 操作時(shí)可以處理其他事情)眶诈。
- 提升用戶體驗(yàn)性涨醋,避免卡頓,縮短等待時(shí)間
- 并行處理逝撬,提高性能浴骂,通常用于服務(wù)器(例如 Tomcat),用多個(gè)線程去處理接收的 HTTP 請(qǐng)求宪潮。
- 在 Android 開(kāi)發(fā)中溯警,主線程的任務(wù)之一就是繪制屏幕, 主線程不允許進(jìn)行IO 操作或網(wǎng)絡(luò)請(qǐng)求狡相,目的就是為了避免卡頓愧膀,影響用戶的體驗(yàn)。
2.2 便于編程建模
將大的任務(wù)分割為多個(gè)小任務(wù)谣光,分別建立程序模型檩淋,并通過(guò)多線程分別運(yùn)行這幾個(gè)任務(wù)。
2.3 計(jì)算機(jī)的性能定律
- 摩爾定律失效
摩爾定律——當(dāng)價(jià)格不變時(shí)萄金,集成電路上可容納的元器件的數(shù)目每個(gè) 18-24 個(gè)月就會(huì)翻一倍以上蟀悦,性能也會(huì)提升一倍。
- 阿姆達(dá)爾定律(Amdahl)登臺(tái)
阿姆達(dá)爾定律:處理器越多氧敢,程序執(zhí)行就越快日戈,但有上限,取決于程序中串行部分的比例孙乖,并行的比例越高浙炼,多處理器的效果越明顯。
最下面藍(lán)色曲線唯袄,當(dāng)并行的比例為 50% 時(shí)弯屈,最快速度可以提升2倍;最上面綠色曲線恋拷,當(dāng)并行的比例為 95% 時(shí)资厉,最快速度可以提升20倍。
3.多線程使用場(chǎng)景
- 后臺(tái)線程蔬顾,如執(zhí)行定時(shí)任務(wù)宴偿。
- tomcat——每次有一個(gè)新的請(qǐng)求過(guò)來(lái)的時(shí)候湘捎,tomcat 會(huì)把這個(gè)請(qǐng)求交給一個(gè)新的線程去處理。
- 多線程后臺(tái)并行下載文件窄刘。
4.多線程的風(fēng)險(xiǎn)
4.1 安全性問(wèn)題
當(dāng)多個(gè)線程同時(shí)訪問(wèn)和修改相同的變量時(shí)窥妇,將會(huì)在串行編程模型中引入非串行因素,如 i++ 的數(shù)據(jù)錯(cuò)誤娩践。
4.2 活躍性問(wèn)題
當(dāng)某個(gè)操作無(wú)法繼續(xù)執(zhí)行下去的時(shí)候活翩,就會(huì)發(fā)生活躍性問(wèn)題,如死鎖欺矫、饑餓以及活鎖。
4.3 性能問(wèn)題
在多線程程序中展氓,當(dāng)線程調(diào)度器臨時(shí)掛起活躍線程并轉(zhuǎn)而運(yùn)行另一個(gè)線程時(shí)穆趴,就會(huì)頻繁得出現(xiàn)上下文切換操作(Context Switch),這種操作會(huì)帶來(lái)極大的開(kāi)銷:保存和恢復(fù)執(zhí)行上下文遇汞,丟失局部性未妹,并且 CPU 將更多的時(shí)間花在線程調(diào)度而不是線程運(yùn)行上。當(dāng)線程共享數(shù)據(jù)時(shí)空入,必須使用同步機(jī)制络它,而這些機(jī)制往往會(huì)抑制某些編譯器優(yōu)化,使內(nèi)存緩沖區(qū)的數(shù)據(jù)無(wú)效歪赢,以及增加共享內(nèi)存總線的同步流量化戳。這些因素都將帶來(lái)額外的性能開(kāi)銷。
三埋凯、串行点楼、并行、并發(fā)
1.串行
串行是將多個(gè)任務(wù)按順序排隊(duì)執(zhí)行白对,例如:聽(tīng)完音樂(lè)再寫代碼掠廓。
2.并行
真正的“同時(shí)”運(yùn)行,在同一時(shí)刻有多個(gè)任務(wù)執(zhí)行甩恼,需要多核處理器蟀瞧,因?yàn)閱魏颂幚砥鳠o(wú)法在同一時(shí)刻執(zhí)行多個(gè)任務(wù)。例如:邊聽(tīng)音樂(lè)邊寫代碼条摸。
3.并發(fā)
- 兩個(gè)或多個(gè)任務(wù)可以在重疊時(shí)間段內(nèi)啟動(dòng)悦污,運(yùn)行和完成。
- 并行(兩個(gè)線程同時(shí)執(zhí)行)一定是并發(fā)钉蒲,并發(fā)并不一定是并行塞关。
- 例如一會(huì)兒聽(tīng)音樂(lè),一會(huì)兒寫代碼子巾,輪流執(zhí)行帆赢。
4.高并發(fā)
4.1 概念
同時(shí)有很多個(gè)請(qǐng)求發(fā)送給服務(wù)器系統(tǒng)小压,服務(wù)器并行處理請(qǐng)求。
4.2 多線程和高并發(fā)
高并發(fā)是一種狀態(tài)椰于,多線程是高并發(fā)的一種重要解決方案怠益,高并發(fā)并不意味著多線程。
4.3 高并發(fā)指標(biāo)
- QPS(Queries Per Second)
- 帶寬
- PV (Page View)
- UV(Unique Visitor)
- 吞吐率(Requests Per Second)
- 并發(fā)連接數(shù)(The number of concurrent connections)
- 服務(wù)器平均請(qǐng)求等待時(shí)間(Time per request: across all concurrent requests)
五瘾婿、同步蜻牢、異步、阻塞偏陪、非阻塞
1.同步與異步
- 同步和異步關(guān)注的是消息通信機(jī)制抢呆,這里指的是調(diào)用者的行為,表示請(qǐng)求是串行還是并行笛谦。
- 同步(Synchronous):客戶端發(fā)出一個(gè)請(qǐng)求后抱虐,一直等到服務(wù)端返回最終的結(jié)果。
- 異步(Asynchronous):客戶端發(fā)出一個(gè)請(qǐng)求后饥脑,還可以發(fā)出另外的請(qǐng)求恳邀,不用等待之前請(qǐng)求的結(jié)果返回。
2.阻塞與非阻塞
- 阻塞非阻塞關(guān)注的程序在等待調(diào)用結(jié)果(消息灶轰,返回值)時(shí)的狀態(tài)谣沸,強(qiáng)調(diào)狀態(tài)。
- 阻塞:客戶端發(fā)起一個(gè)請(qǐng)求后笋颤,當(dāng)前線程會(huì)被掛起乳附,直到服務(wù)端返回結(jié)果。
- 非阻塞:客戶端發(fā)起一個(gè)請(qǐng)求后伴澄,不管服務(wù)器會(huì)不會(huì)立刻返回結(jié)果许溅,當(dāng)前線程都不會(huì)被掛起。
3.例子
水壺?zé)睦颖妫袃煞N水壺贤重,一種普通水壺,只能自己觀察水是否燒開(kāi)清焕;一種帶提醒的水壺并蝗,水燒開(kāi)會(huì)有聲音提醒。
- 同步阻塞:用普通水壺?zé)胀祝恢钡戎撍畨氐乃疅_(kāi)滚停。
- 同步非阻塞:用普通水壺?zé)缓笕タ蛷d看電視粥惧,時(shí)不時(shí)觀察水燒開(kāi)了沒(méi)键畴。
- 異步阻塞:用帶提醒的水壺?zé)恢钡戎撍畨氐乃疅_(kāi)。
- 異步非阻塞:用帶提醒的水壺?zé)鹛瑁缓笕ネ媸謾C(jī)涡贱,直到該水壺發(fā)出聲音提醒。
《Java并發(fā)編程實(shí)戰(zhàn)》