php中線程、協(xié)程的理解
1、線程
線程也叫輕量級進程,它是一個基本的CPU執(zhí)行單元,也是程序執(zhí)行過程中的最小單元,由線程ID、程序計數(shù)器、寄存器集合和堆棧共同組成。線程的引入減小了程序并發(fā)執(zhí)行時的開銷,提高了操作系統(tǒng)的并發(fā)性能。線程沒有自己的系統(tǒng)資源。
線程較之進程,其優(yōu)勢在于一個快,不管是創(chuàng)建新的線程還是終止一個線程;不管是線程間的切換還是線程間共享數(shù)據(jù)或通信,其速度與進程相比都有較大的優(yōu)勢。
線程的出現(xiàn)是為了降低上下文切換的消耗,提高系統(tǒng)的并發(fā)性,并突破一個進程只能干一樣事的缺陷,使到進程內(nèi)并發(fā)成為可能。
2、協(xié)程
協(xié)程就是用戶態(tài)的線程,要理解是什么是“用戶態(tài)的線程”,必然就要先理解什么是“內(nèi)核態(tài)的線程”。 內(nèi)核態(tài)的線程是由操作系統(tǒng)來進行調(diào)度的,在切換線程上下文時,要先保存上一個線程的上下文,然后執(zhí)行下一個線程,當(dāng)條件滿足時,切換回上一個線程,并恢復(fù)上下文。 協(xié)程也是如此,只不過,用戶態(tài)的線程不是由操作系統(tǒng)來調(diào)度的,而是由程序員來調(diào)度的,是在用戶態(tài)的。
yield
這個關(guān)鍵字就是用來產(chǎn)生中斷,并保存當(dāng)前的上下文的,比如說程序的一段代碼是訪問遠(yuǎn)程服務(wù)器,那這個時候CPU就是空閑的,就用yield讓出CPU,接著執(zhí)行下一段的代碼,如果下一段代碼還是訪問除CPU以外的其它資源,還可以調(diào)用yield讓出CPU. 繼續(xù)往下執(zhí)行,這樣就可以用同步的方式寫異步的代碼了。
①協(xié)程的出現(xiàn)
在協(xié)程出現(xiàn)之前,要實現(xiàn)多任務(wù)并發(fā),在無OS(操作系統(tǒng))時代,可以使用狀態(tài)機的思想對多任務(wù)進行拆解,在單進程環(huán)境中運行多任務(wù),但是這種模式下需要開發(fā)者對每個任務(wù)有清晰的了解,也要開發(fā)者自行開發(fā)與任務(wù)相關(guān)功能(如任務(wù)間的通訊)。
后來出現(xiàn)了OS(操作系統(tǒng)),咱們就開始使用OS提供的進程和線程功能來輕易實現(xiàn)多任務(wù)了。在OS中,程的上下文切換是OS內(nèi)核控制。但是后來卻出現(xiàn)了一個問題,頻繁的進程上下文切換導(dǎo)致了OS性能的降低(主要是短時執(zhí)行消耗小的任務(wù)進程)。
為了解決這個問題,開始提出新的概念,就是在同一進程或線程中運行多個任務(wù),這種問題就相當(dāng)于回到了早期的無OS時代的多任務(wù)實現(xiàn)。而現(xiàn)在解決方案稱為協(xié)程。其本質(zhì)是,將將任務(wù)切換的部分工作從內(nèi)核轉(zhuǎn)移到應(yīng)用層。
②php中協(xié)程的基本工具以及基本使用
要實現(xiàn)協(xié)程,php給出了兩個新東西:生成器和yield關(guān)鍵字。
(1)什么是生成器?
生成器繼承了實現(xiàn)了迭代器,在php代碼中和函數(shù)的定義類似,不過內(nèi)部使用了yield關(guān)鍵字,如:
使用時,這樣子:
好了,這樣使用代表什么意思呢?
(1)首先$my_gen = gen();這句代碼只是實例化一個新的生成器,里面的代碼并未執(zhí)行;
(2)$my_gen->current();這句代碼就執(zhí)行了生成器里面的step2中的yield “gen1”了,這時代碼中斷,并且字符串“gen1”被傳進了生成器$my_gen,并且作為current()函數(shù)的返回值;
這里如果繼續(xù)用current()方法來調(diào)取,則結(jié)果也不變,$my_gen的返回值仍然是gen1
(3)send(“main send”)執(zhí)行完之后,字符串”main send”被傳遞進了生成器$my_gen, 同時生成器作為step2中yield的返回值傳遞給ret; 通過send()方法則會找到之前的上下文,并繼續(xù)向下走。
(4) 生成器step3執(zhí)行完后,在step4時,遇到y(tǒng)ield就會再次進入中斷。
以上內(nèi)容僅供參考!
推薦教程:PHP視頻教程