一疫鹊、進(jìn)程
進(jìn)程是系統(tǒng)中資源分配和運(yùn)行調(diào)度的單位,在對(duì)資源的共享和競爭中司致,進(jìn)程間會(huì)相互制約拆吆。從結(jié)構(gòu)上講,每個(gè)進(jìn)程都由程序脂矫、數(shù)據(jù)和一個(gè)進(jìn)程控制塊(Process Control Block, PCB
)組成枣耀。
也可以理解為一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng),是系統(tǒng)進(jìn)行資源分配和調(diào)度運(yùn)行的基本單位庭再。
- 進(jìn)程是操作系統(tǒng)對(duì)一個(gè)正在運(yùn)行的程序的一種抽象結(jié)構(gòu)捞奕。
- 進(jìn)程是指在操作系統(tǒng)中能獨(dú)立運(yùn)行并作為資源分配的基本單位,由一組機(jī)器指令拄轻、數(shù)據(jù)和堆棧等組成的能獨(dú)立運(yùn)行的活動(dòng)實(shí)體颅围。
- 操作系統(tǒng)可以同時(shí)運(yùn)行多個(gè)進(jìn)程,多個(gè)進(jìn)程直接可以并發(fā)執(zhí)行和交換信息恨搓。
- 進(jìn)程在運(yùn)行是需要一定的資源院促,如CPU筏养、存儲(chǔ)空間和I/O設(shè)備等。
1常拓、進(jìn)程的重要特征
進(jìn)程最基本的特征是并發(fā)和共享特征
- 動(dòng)態(tài)特征:進(jìn)程對(duì)應(yīng)于程序的運(yùn)行渐溶,動(dòng)態(tài)產(chǎn)生、消亡弄抬,在其生命周期中進(jìn)程也是動(dòng)態(tài)的茎辐、
- 并發(fā)特征:任何進(jìn)程都可以同其他進(jìn)程一起向前推進(jìn)
- 獨(dú)立特征:進(jìn)程是相對(duì)完整的調(diào)度單位,可以獲得CPU掂恕,參與并發(fā)執(zhí)行
- 交往特征:一個(gè)進(jìn)程在執(zhí)行過程中可與其他進(jìn)程產(chǎn)生直接或間接關(guān)系
- 異步特征:每個(gè)進(jìn)程都以相對(duì)獨(dú)立拖陆、不可預(yù)知的速度向前推進(jìn)
- 結(jié)構(gòu)特征:每個(gè)進(jìn)程都有一個(gè)PCB作為他的數(shù)據(jù)結(jié)構(gòu)
2、進(jìn)程的狀態(tài)與轉(zhuǎn)換
- 進(jìn)程的三種基本狀態(tài)
- a. 運(yùn)行狀態(tài):獲得CPU的進(jìn)程處于此狀態(tài)竹海,對(duì)應(yīng)的程序在CPU上運(yùn)行著
- b. 阻塞狀態(tài):為了等待某個(gè)外部事件的發(fā)生(如等待I/O操作的完成慕蔚,等待另一個(gè)進(jìn)程發(fā)來消息),暫時(shí)無法運(yùn)行斋配。也成為等待狀態(tài)
- c. 就緒狀態(tài):具備了一切運(yùn)行需要的條件孔飒,由于其他進(jìn)程占用CPU而暫時(shí)無法運(yùn)行
- 進(jìn)程狀態(tài)轉(zhuǎn)換
- a. 運(yùn)行狀態(tài) ===> 阻塞狀態(tài):例如正在運(yùn)行的進(jìn)程提出I/O請(qǐng)求朝聋,由運(yùn)行狀態(tài)轉(zhuǎn)化為阻塞狀態(tài)
- b. 阻塞狀態(tài) ===> 就緒狀態(tài):例如I/O操作完成之后暖释,由阻塞狀態(tài)轉(zhuǎn)化為就緒狀態(tài)
- c. 就緒狀態(tài) ===> 運(yùn)行狀態(tài):例如就緒狀態(tài)的進(jìn)程被進(jìn)程調(diào)度程序選中,分配到CPU中運(yùn)行脆栋,由就緒狀態(tài)轉(zhuǎn)化為運(yùn)行狀態(tài)
- d. 運(yùn)行狀態(tài) ===> 就緒狀態(tài):處于運(yùn)行狀態(tài)的進(jìn)程的時(shí)間片用完甩卓,不得不讓出CPU鸠匀,由運(yùn)行狀態(tài)轉(zhuǎn)化為就緒狀態(tài)
- 進(jìn)程的類型
- a. 系統(tǒng)進(jìn)程:操作系統(tǒng)用來管理資源的進(jìn)程,當(dāng)系統(tǒng)進(jìn)程處于運(yùn)行態(tài)時(shí)逾柿,CPU處于管態(tài)缀棍,系統(tǒng)之間的關(guān)系由操作系統(tǒng)負(fù)責(zé)
- b. 用戶進(jìn)程:操作系統(tǒng)可以獨(dú)立執(zhí)行的的用戶程序段,當(dāng)用戶進(jìn)程處于運(yùn)行態(tài)時(shí)机错,CPU處于目態(tài)爬范,用戶進(jìn)程之間的關(guān)系由用戶負(fù)責(zé)
二、線程概念
在一個(gè)程序里的一個(gè)執(zhí)行路線就叫做線程(thread)弱匪。更準(zhǔn)確的定義是:線程是“一個(gè)進(jìn)程內(nèi)部的
控制序列”青瀑。一切進(jìn)程至少都有一個(gè)執(zhí)行線程。
線程是程序中一個(gè)單一的順序控制流程萧诫。進(jìn)程內(nèi)有一個(gè)相對(duì)獨(dú)立的斥难、可調(diào)度的執(zhí)行單元,是系統(tǒng)獨(dú)立調(diào)度和分派CPU的基本單位指令運(yùn)行時(shí)的程序的調(diào)度單位帘饶。在單個(gè)程序中同時(shí)運(yùn)行多個(gè)線程完成不同的工作哑诊,稱為多線程。
- 線程比進(jìn)程更輕量
- 線程能獨(dú)立運(yùn)行及刻,獨(dú)立調(diào)度搭儒,擁有資源(一般是CPU資源穷当,程序計(jì)數(shù)器等)
- 線程調(diào)度能大幅度減小調(diào)度的成本(相對(duì)于進(jìn)程來說),線程的切換不會(huì)引起進(jìn)程的切換
- 線程的引入進(jìn)一步提高了操作系統(tǒng)的并發(fā)性淹禾,線程能并發(fā)執(zhí)行
- 同一個(gè)進(jìn)程的多個(gè)線程共享進(jìn)程的資源(省去了資源調(diào)度現(xiàn)場保護(hù)的很多工作)
1、多線程中的三個(gè)核心概念
并發(fā)編程三個(gè)問題:原子性問題茴扁,可見性問題铃岔,有序性問題。
多線程同步是指多個(gè)線程訪問鎖定的代碼段時(shí)峭火,必須按照每個(gè)線程獲取該代碼段鎖的順序執(zhí)行毁习。
1.1、原子性
這一點(diǎn)卖丸,跟數(shù)據(jù)庫事務(wù)的原子性概念差不多纺且,即一個(gè)操作(有可能包含有多個(gè)子操作)要么全部執(zhí)行(生效),要么全部都不執(zhí)行(都不生效)稍浆。
1.2载碌、可見性
可見性是指,當(dāng)多個(gè)線程并發(fā)訪問共享變量時(shí)衅枫,一個(gè)線程對(duì)共享變量的修改嫁艇,其它線程能夠立即看到∠伊茫可見性問題是好多人忽略或者理解錯(cuò)誤的一點(diǎn)步咪。
CPU從主內(nèi)存中讀數(shù)據(jù)的效率相對(duì)來說不高,現(xiàn)在主流的計(jì)算機(jī)中益楼,都有幾級(jí)緩存猾漫。每個(gè)線程讀取共享變量時(shí),都會(huì)將該變量加載進(jìn)其對(duì)應(yīng)CPU的高速緩存里感凤,修改該變量后悯周,CPU會(huì)立即更新該緩存,但并不一定會(huì)立即將其寫回主內(nèi)存(實(shí)際上寫回主內(nèi)存的時(shí)間不可預(yù)期)俊扭。此時(shí)其它線程(尤其是不在同一個(gè)CPU上執(zhí)行的線程)訪問該變量時(shí)队橙,從主內(nèi)存中讀到的就是舊的數(shù)據(jù),而非第一個(gè)線程更新后的數(shù)據(jù)萨惑。
這一點(diǎn)是操作系統(tǒng)或者說是硬件層面的機(jī)制捐康,所以很多應(yīng)用開發(fā)人員經(jīng)常會(huì)忽略。
1.3庸蔼、順序性
順序性指的是解总,程序執(zhí)行的順序按照代碼的先后順序執(zhí)行。
2姐仅、線程安全
線程安全
:就是多線程訪問時(shí)花枫,采用了加鎖機(jī)制刻盐,當(dāng)一個(gè)線程訪問該類的某個(gè)數(shù)據(jù)時(shí),進(jìn)行保護(hù)劳翰,其他線程不能進(jìn)行訪問直到該線程讀取完敦锌,其他線程才可使用。不會(huì)出現(xiàn)數(shù)據(jù)不一致或者數(shù)據(jù)污染佳簸。
線程不安全
:就是不提供數(shù)據(jù)訪問保護(hù)乙墙,有可能出現(xiàn)多個(gè)線程先后更改數(shù)據(jù)造成所得到的數(shù)據(jù)是臟數(shù)據(jù)。
只要線程之間沒有共享資源生均,那么就是線程安全的听想,有共享資源,為了保證線程安全马胧,需要引進(jìn)鎖的機(jī)制汉买。
編寫線程安全的代碼,核心在于要對(duì)狀態(tài)訪問操作進(jìn)行管理佩脊,特別是對(duì)共享的(Shared)和可變的(Mutable)狀態(tài)的訪問蛙粘。對(duì)象的狀態(tài)是指存儲(chǔ)在狀態(tài)變量(實(shí)例或靜態(tài)域)中的數(shù)據(jù)。對(duì)象的狀態(tài)還可能包括其他依賴對(duì)象的域邻吞。(Map.Entry)
進(jìn)程調(diào)度可以很好的控制資源分配组题,線程調(diào)度讓進(jìn)程內(nèi)部不因某個(gè)操作阻塞而整體阻塞。協(xié)程則是在用戶態(tài)來優(yōu)化程序抱冷,讓程序員以寫同步代碼的方式寫出異步代碼般的效率崔列。
三、協(xié)程
關(guān)于協(xié)程旺遮,你可能看的最多的就是這樣一句話“協(xié)程就是用戶態(tài)的輕量級(jí)的線程”.
要理解是什么是“用戶態(tài)的線程”赵讯,必然就要先理解什么是“內(nèi)核態(tài)的線程”。 內(nèi)核態(tài)的線程是由操作系統(tǒng)來進(jìn)行調(diào)度的耿眉,在切換線程上下文時(shí)边翼,要先保存上一個(gè)線程的上下文,然后執(zhí)行下一個(gè)線程鸣剪,當(dāng)條件滿足時(shí)组底,切換回上一個(gè)線程,并恢復(fù)上下文筐骇。 協(xié)程也是如此债鸡,只不過,用戶態(tài)的線程不是由操作系統(tǒng)來調(diào)度的铛纬,而是由程序員來調(diào)度的厌均,是在用戶態(tài)的。
- 協(xié)程是用戶模式下的輕量級(jí)線程告唆,操作系統(tǒng)內(nèi)核對(duì)協(xié)程一無所知
- 協(xié)程的調(diào)度完全有應(yīng)用程序來控制棺弊,操作系統(tǒng)不管這部分的調(diào)度
- 一個(gè)線程可以包含一個(gè)或多個(gè)協(xié)程
- 協(xié)程擁有自己的寄存器上下文和棧晶密,協(xié)程調(diào)度切換時(shí),將寄存器上下紋和棧保存起來模她,在切換回來時(shí)恢復(fù)先前保運(yùn)的寄存上下文和棧
- 協(xié)程能保留上一次調(diào)用時(shí)的狀態(tài)稻艰,看到這里各種生成器(生成器是被閹割的協(xié)程)的概念浮現(xiàn)出來了。侈净。
- Windows下的實(shí)現(xiàn)叫纖程
3.1连锯、實(shí)現(xiàn)一個(gè)用戶態(tài)線程有兩個(gè)必須要處理的問題:
- 一是碰著阻塞式I\O會(huì)導(dǎo)致整個(gè)進(jìn)程被掛起;
- 二是由于缺乏時(shí)鐘阻塞用狱,進(jìn)程需要自己擁有調(diào)度線程的能力。
如果一種實(shí)現(xiàn)使得每個(gè)線程需要自己通過調(diào)用某個(gè)方法拼弃,主動(dòng)交出控制權(quán)夏伊。那么我們就稱這種用戶態(tài)線程是協(xié)作式的,即是協(xié)程吻氧。
3.2溺忧、為什么要用協(xié)程,協(xié)程有助于以下實(shí)現(xiàn)
- 狀態(tài)機(jī):在一個(gè)子例程里實(shí)現(xiàn)狀態(tài)機(jī)盯孙,這里狀態(tài)由該過程當(dāng)前的出口/入口點(diǎn)確定鲁森;這可以產(chǎn)生可讀性更高的代碼。
- 角色模型:并行的角色模型振惰,例如計(jì)算機(jī)游戲歌溉。每個(gè)角色有自己的過程(這又在邏輯上分離了代碼),但他們自愿地向順序執(zhí)行各角色過程的中央調(diào)度器交出控制(這是合作式多任務(wù)的一種形式)骑晶。
- 產(chǎn)生器:它有助于輸入/輸出和對(duì)數(shù)據(jù)結(jié)構(gòu)的通用遍歷痛垛。
四、程序桶蛔,進(jìn)程匙头,線程這三者之間的關(guān)系?
進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)用的獨(dú)立單位仔雷,每一個(gè)進(jìn)程蹂析,都由它自己的內(nèi)存空間和系統(tǒng)資源;線程是進(jìn)程的執(zhí)行單元碟婆,執(zhí)行路徑电抚,線程也是程序使用CPU的最基本單位。
簡單來說脑融,一程序可以調(diào)用多個(gè)進(jìn)程喻频,比如一個(gè)視頻播放器程序,里面就存在兩個(gè)進(jìn)程:一個(gè)是播放視頻的進(jìn)程肘迎,一個(gè)是下載上傳視頻的進(jìn)程甥温。
一個(gè)進(jìn)程又同時(shí)調(diào)用多個(gè)線程锻煌,這個(gè)線程是隱藏的,用進(jìn)程管理器看不到姻蚓,可用其它的進(jìn)程管理軟件來查看宋梧。
三者的邏輯關(guān)系是程序調(diào)用進(jìn)程,進(jìn)程調(diào)用線程狰挡,一般來說程序下面都是多進(jìn)程捂龄,不同的進(jìn)程分工不同;進(jìn)程下面也基本上是多線程的加叁。
4.1倦沧、進(jìn)程和線程的區(qū)別
- 進(jìn)程是資源競爭的基本單位
- 線程是程序執(zhí)行的最小單位
- 線程共享進(jìn)程數(shù)據(jù),但也擁有?自?己的一部分?jǐn)?shù)據(jù)它匕。
4.2展融、線程和協(xié)程的區(qū)別
一旦創(chuàng)建完線程,你就無法決定他什么時(shí)候獲得時(shí)間片豫柬,什么時(shí)候讓出時(shí)間片了告希,你把它交給了內(nèi)核。而協(xié)程編寫者可以有一是可控的切換時(shí)機(jī)烧给,二是很小的切換代價(jià)燕偶。從操作系統(tǒng)有沒有調(diào)度權(quán)上看,協(xié)程就是因?yàn)椴恍枰M(jìn)行內(nèi)核態(tài)的切換础嫡,所以會(huì)使用它指么。
三種調(diào)度的技術(shù)雖然有相似的地方,但并不沖突驰吓。進(jìn)程調(diào)度可以很好的控制資源分配涧尿,線程調(diào)度讓進(jìn)程內(nèi)部不因某個(gè)操作阻塞而整體阻塞。協(xié)程則是在用戶態(tài)來優(yōu)化程序檬贰,讓程序員以寫同步代碼的方式寫出異步代碼般的效率姑廉。
五、PHP的TSRM
線程安全資源管理器(Thread Safe Resource Manager)翁涤,這是個(gè)嘗嘗被忽視桥言,并很少被人說起的“層”(layer), 她在PHP源碼的/TSRM目錄下。
PHP實(shí)現(xiàn)的線程安全主要是使用TSRM
機(jī)制對(duì) 全局變量和靜態(tài)變量進(jìn)行了隔離葵礼,將全局變量和靜態(tài)變量給每個(gè)線程都復(fù)制了一份号阿,各線程使用的都是主線程的一個(gè)備份,從而避免了變量沖突鸳粉,也就不會(huì)出現(xiàn)線程安全問題扔涧。
PHP對(duì)多線程的封裝保證了線程安全,程序員不用考慮對(duì)全局變量加各種鎖來避免讀寫沖突了,同時(shí)也減少了出錯(cuò)的機(jī)會(huì)枯夜,寫出的代碼更加安全弯汰。
但由此導(dǎo)致的是,子線程一旦開始運(yùn)行湖雹,主線程便無法再對(duì)子線程運(yùn)行細(xì)節(jié)進(jìn)行調(diào)整了咏闪,線程一定程度上失去了線程之間通過全局變量進(jìn)行消息傳遞的能力。
同時(shí)PHP開啟線程安全選項(xiàng)后摔吏,使用TSRM
機(jī)制分配和使用變量時(shí)也會(huì)有額外的損耗鸽嫂,所以在不需要多線程的PHP環(huán)境中,使用PHP的ZTS
(非線程安全) 版本就好征讲。
六据某、參考
1、進(jìn)程诗箍,線程哗脖,協(xié)程
2、Java進(jìn)階(二)當(dāng)我們說線程安全時(shí)扳还,到底在說什么
3、線程橱夭,線程安全與python的GIL鎖
4氨距、并發(fā)基礎(chǔ)知識(shí) — 線程安全性
5、PHP的生成器棘劣、yield和協(xié)程
6俏让、PHP中被忽略的性能優(yōu)化利器:生成器
7、在PHP中使用協(xié)程實(shí)現(xiàn)多任務(wù)調(diào)度
8茬暇、多線程編程 - PHP 實(shí)現(xiàn)
9首昔、PHP 進(jìn)階之路 - 揭開 PHP 線程安全的神秘面紗
10、進(jìn)程詳解(1)——可能是最深入淺出的進(jìn)程學(xué)習(xí)筆記
11糙俗、操作系統(tǒng) - 進(jìn)程的概念
12勒奇、進(jìn)程、線程巧骚、協(xié)程
13赊颠、進(jìn)程 線程 協(xié)程 管程 纖程 概念對(duì)比理解