串行和并行的区别_入门参考:从Go中的协程理解串行和并行
本文轉(zhuǎn)自公眾號(hào)語(yǔ)言隨筆,歡迎關(guān)注
入門(mén)參考:從Go中的協(xié)程理解串行和并行?mp.weixin.qq.comGo語(yǔ)言的設(shè)計(jì)亮點(diǎn)之一就是原生實(shí)現(xiàn)了協(xié)程,并優(yōu)化了協(xié)程的使用方式。使得用Go來(lái)處理高并發(fā)問(wèn)題變得更加簡(jiǎn)單。今天我們來(lái)看一下Go中的協(xié)程。
從串行到并行
在處理器還是單個(gè)單核的時(shí)候,這個(gè)時(shí)候并不存在并行,因?yàn)橹挥幸粋€(gè)處理器。所以那時(shí)候的編程都是串行編程。程序執(zhí)行都是從頭順序執(zhí)行到尾。到了多處理器多核的時(shí)代,為了充分利用處理器的處理能力,開(kāi)始出現(xiàn)了并發(fā)編程。開(kāi)發(fā)者開(kāi)始在進(jìn)程中啟用多個(gè)線程來(lái)執(zhí)行操作,利用CPU的調(diào)度能力來(lái)最大化程序處理效率。
并發(fā),并行
在說(shuō)到并發(fā)編程的時(shí)候總會(huì)遇到這兩個(gè)概念,面試的時(shí)候也會(huì)問(wèn)道,在這里就簡(jiǎn)單說(shuō)一下這兩者的區(qū)別:
并發(fā)是一種能力,是指多個(gè)任務(wù)在一段時(shí)間內(nèi)同時(shí)發(fā)生。 并行值得是多個(gè)任務(wù)同時(shí)發(fā)生,就是并行。并發(fā)值得是并行的能力,并發(fā)不一定是同時(shí)發(fā)生,可能是同一時(shí)間段內(nèi)交替發(fā)生。
進(jìn)程,線程,協(xié)程
進(jìn)程和線程是操作系統(tǒng)的基本概念:
進(jìn)程:指計(jì)算機(jī)中已運(yùn)行的程序,進(jìn)程是程序的基本執(zhí)行實(shí)體。 線程:是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。它被包含在進(jìn)程中,是進(jìn)程的實(shí)際運(yùn)行單位。那么協(xié)程是在線程之上,更加輕量級(jí)的設(shè)計(jì)。協(xié)程因?yàn)橹还ぷ髟谟脩艨丶?#xff0c;沒(méi)有線程上下文切換帶來(lái)的消耗。協(xié)程的調(diào)度由用戶手動(dòng)切換,所以更加靈活。
協(xié)程的另一大優(yōu)勢(shì)就是因?yàn)樵谟脩艨臻g調(diào)度,所以不會(huì)出現(xiàn)代碼執(zhí)行一半被強(qiáng)制中斷,所以無(wú)需原子操作鎖。
Go中的協(xié)程
在Go中使用協(xié)程非常簡(jiǎn)單,就使用go關(guān)鍵字就可以了。我們來(lái)看一段串行代碼使用協(xié)程如何進(jìn)行操作:
package mainimport ("fmt""time" )func main(){print1To10() }func print1To10(){for i := 1; i<=10; i++{fmt.Printf("%d ", i)} }// 輸出 // 1 2 3 4 5 6 7 8 9 10那么使用協(xié)程,我們來(lái)看一下運(yùn)行結(jié)果:
package mainimport ("fmt""time" )func main(){fmt.Println("before go coroutine")go print1To10()fmt.Println("after go coroutine")time.Sleep(100 * time.Millisecond) //防止主協(xié)程直接結(jié)束了,打印協(xié)程還沒(méi)來(lái)得及執(zhí)行 }func print1To10(){for i := 1; i<=10; i++{fmt.Printf("%d ", i)} }// 輸出 /*********** before go coroutine after go coroutine 1 2 3 4 5 6 7 8 9 10 *************/我們可以看出使用go關(guān)鍵詞后,打印并不是按照順序串行執(zhí)行的,而是在主協(xié)程執(zhí)行結(jié)束后,打印協(xié)程才開(kāi)始執(zhí)行。
Go協(xié)程的調(diào)度機(jī)制
Go中的協(xié)程調(diào)度模型是G-P-M模型:
G代表Goroutine,也就是Go中的協(xié)程對(duì)象。 P代表Processor,代表虛擬的處理器。一般來(lái)說(shuō),和邏輯核一一對(duì)應(yīng)。 M代表Machine,實(shí)際上是操作系統(tǒng)的線程。這里我們簡(jiǎn)單說(shuō)一下Go的調(diào)度機(jī)制,感興趣或者有了解的可以自行看Go的源碼:
其中第4條 盡可能獲取G 則是Go的有趣的設(shè)計(jì)理念之一,當(dāng)一個(gè) P 發(fā)現(xiàn)自己的 LRQ 已經(jīng)沒(méi)有 G 時(shí),會(huì)從其他 P “偷” 一些 G 來(lái)運(yùn)行。看看這是什么精神!自己的工作做完了,為了全局的利益,主動(dòng)為別人分擔(dān)。這被稱為 Work-stealing。
再看串行和并行
這里我們以Go協(xié)程來(lái)繼續(xù)說(shuō)一下串行和并行,對(duì)于習(xí)慣于串行編程的程序員來(lái)說(shuō),理解并行可能稍微需要點(diǎn)時(shí)間,對(duì)于程序設(shè)計(jì)來(lái)說(shuō),并行的設(shè)計(jì)主要是為了提高程序運(yùn)行的效率,使得程序能夠充分利用多核多處理器的資源(或者多機(jī)器)。那么對(duì)于如何充分利用,大部分支持并行編程的語(yǔ)言都有其內(nèi)部的調(diào)度機(jī)制,即使沒(méi)有,也會(huì)使用系統(tǒng)的調(diào)度機(jī)制--線程調(diào)度。
那么對(duì)于并行調(diào)度機(jī)制總體上分為兩類(lèi):協(xié)作式和搶占式
協(xié)作式:一個(gè)任務(wù)得到了 CPU 時(shí)間,除非它自己放棄使用 CPU ,否則將完全霸占 CPU ,所以任務(wù)之間需要協(xié)作使用一段時(shí)間的 CPU ,放棄使用,其它的任務(wù)也如此,才能保證系統(tǒng)的正常運(yùn)行。如果有一個(gè)任務(wù)死鎖,則系統(tǒng)也同樣死鎖。搶占式:總控制權(quán)在操作系統(tǒng)手中,操作系統(tǒng)會(huì)輪流詢問(wèn)每一個(gè)任務(wù)是否需要使用 CPU ,需要使用的話就讓它用,不過(guò)在一定時(shí)間后,操作系統(tǒng)會(huì)剝奪當(dāng)前任務(wù)的 CPU 使用權(quán),把它排在詢問(wèn)隊(duì)列的最后,再去詢問(wèn)下一個(gè)任務(wù)。如果有一個(gè)任務(wù)死鎖,系統(tǒng)仍能正常運(yùn)行。
在 Go1.1 版本中,調(diào)度器還不支持搶占式調(diào)度,只能依靠 goroutine 主動(dòng)讓出 CPU 資源,存在非常嚴(yán)重的調(diào)度問(wèn)題。
Go1.12 中編譯器在特定時(shí)機(jī)插入函數(shù),通過(guò)函數(shù)調(diào)用作為入口觸發(fā)搶占,實(shí)現(xiàn)了協(xié)作式的搶占式調(diào)度。但是這種需要函數(shù)調(diào)用主動(dòng)配合的調(diào)度方式存在一些邊緣情況。
后面Go在1.14版本實(shí)現(xiàn)了基于信號(hào)的真搶占式調(diào)度。用于解決解決了垃圾回收和棧掃描時(shí)存在的問(wèn)題。
Go的協(xié)程調(diào)度目前雖然不能稱得上完美,但是對(duì)于我們理解并行有一定的幫助。所謂并行編程,就是開(kāi)啟多個(gè)任務(wù)而不用等待任務(wù)結(jié)果。可以使得相互獨(dú)立的任務(wù)同時(shí)運(yùn)行,比如文件寫(xiě)入等。
總結(jié)
以上是生活随笔為你收集整理的串行和并行的区别_入门参考:从Go中的协程理解串行和并行的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python 下划线转驼峰_json字符
- 下一篇: 华擎b365m itx 黑苹果_迷你IT