日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

串行和并行的区别_入门参考:从Go中的协程理解串行和并行

發(fā)布時(shí)間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 串行和并行的区别_入门参考:从Go中的协程理解串行和并行 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文轉(zhuǎn)自公眾號(hào)語(yǔ)言隨筆,歡迎關(guān)注

入門(mén)參考:從Go中的協(xié)程理解串行和并行?mp.weixin.qq.com

Go語(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的源碼:

  • 在Go程序啟動(dòng)時(shí),會(huì)給每個(gè)邏輯核分配一個(gè)P(虛擬處理器)
  • 同時(shí),Go會(huì)創(chuàng)建一個(gè)主協(xié)程G,來(lái)執(zhí)行程序。新創(chuàng)建的G會(huì)被放到LRQ(P上的本地G隊(duì)列)或者GRQ(全局G隊(duì)列)。
  • 給P分配一個(gè)M(內(nèi)核線程),這些M由OS Scheduler調(diào)度而非Go Scheduler調(diào)度。M用來(lái)運(yùn)行G
  • P會(huì)盡可能獲取G來(lái)運(yùn)行,當(dāng)沒(méi)有G運(yùn)行后,會(huì)銷(xiāo)毀并重新進(jìn)入調(diào)度
  • 其中第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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。