Go語言中單核CPU開兩個Goroutine時其中一個死循環(huán)會怎么樣

本篇文章為大家展示了Go語言中單核CPU開兩個Goroutine時其中一個死循環(huán)會怎么樣,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

從2013年創(chuàng)立創(chuàng)新互聯(lián)專注于”幫助中小企業(yè)+互聯(lián)網(wǎng)”, 也是目前成都地區(qū)具有實力的互聯(lián)網(wǎng)服務(wù)商。團隊致力于為企業(yè)提供--站式網(wǎng)站建設(shè)、移動端應(yīng)用( H5手機營銷、手機APP定制開發(fā)、微信開發(fā))、軟件開發(fā)、信息化解決方案等服務(wù)。

今天的男主角,是與 Go 工程師有調(diào)度相關(guān)的知識,那就是 “單核 CPU,開兩個 Goroutine,其中一個死循環(huán),會怎么樣?

請在此處默念自己心目中的答案,再往和煎魚一起研討一波 Go 的技術(shù)哲學(xué)。

問題定義

針對這個問題,我們需要把問題剖開來看看,其具有以下幾個元素:

  • 運行 Go 程序的計算機只有一個單核 CPU。
  • 兩個 Goroutine 在運行。
  • 一個 Goroutine 死循環(huán)。

根據(jù)這道題的題意,可大致理解其想要問的是 Go 調(diào)度相關(guān)的一些知識理解。

單核 CPU

第一個要點,就是要明確 “計算機只有一個單核 CPU” 這一個變量定義,對 Go 程序會產(chǎn)生什么影響,否則很難繼續(xù)展開。

既然明確涉及 Goroutine,這里就會考察到你對 Go 的調(diào)度模型 GMP 的基本理解了。

從單核 CPU 來看,最大的影響就是 GMP 模型中的 P,因為 P 的數(shù)量默認是與 CPU 核數(shù)(GOMAXPROCS)保持一致的。

  • G:Goroutine,實際上我們每次調(diào)用     go func 就是生成了一個 G。
  • P:Processor,處理器,一般 P 的數(shù)量就是處理器的核數(shù),可以通過     GOMAXPROCS 進行修改。
  • M:Machine,系統(tǒng)線程。

這三者交互實際來源于 Go 的 M: N 調(diào)度模型。也就是 M 必須與 P 進行綁定,然后不斷地在 M 上循環(huán)尋找可運行的 G 來執(zhí)行相應(yīng)的任務(wù)。

Goroutine 受限

第二個要點,就是 Goroutine 的數(shù)量和運行模式都是受限的。有兩個 Goroutine,一個 Goroutine 在死循環(huán),另外一個在正常運行。

這可以理解為 Main Goroutine + 起了一個新 Goroutine 跑著死循環(huán),因為本身 main 函數(shù)就是一個主協(xié)程在運行著,沒毛病。

需要注意的是,Goroutine 里跑著死循環(huán),也就是時時刻刻在運行著 “業(yè)務(wù)邏輯”。這塊需要與單核 CPU 關(guān)聯(lián)起來,考慮是否會一直阻塞住,把整個 Go 進程運行給 hang 住了

注:但若是在現(xiàn)場面試,可以先枚舉出這種場景,詮釋清楚后。再補充提問面試官,是否這類場景?

 

Go 版本的問題

第三個要點,是一個隱性的拓展點。如果你是一個老 Go 粉,經(jīng)常關(guān)注 Go 版本的更新情況(至少大版本),則應(yīng)該會知道 Go 的調(diào)度是會變動的(會在后面的小節(jié)講解)。

因此本文這個問題,在不同的 Go 語言版本中,結(jié)果可能會是不一樣的。但是面試官并沒有指出,這里就需要考慮到:

  1. 面試官故意不指出,等著你指出。
  2. 面試官沒留意到這塊,沒想那么多。
  3. 面試官自己都不知道這塊的 “新” 知識,他的知識可能還是老的。

如果你注意到了,是一個小亮點,說明你在這塊有一定的知識積累。

 

實戰(zhàn)演練

在剛剛過去的 3s 中,你已經(jīng)把上面的考量都在大腦中過了一遍。接下來我們正式進入實戰(zhàn)演練,構(gòu)造一個例子:

// Main Goroutine 
func main() {
    // 模擬單核 CPU
    runtime.GOMAXPROCS(1)
    
    // 模擬 Goroutine 死循環(huán)
    go func() {
        for {
        }
    }()

    time.Sleep(time.Millisecond)
    fmt.Println("腦子進煎魚了")
}
 

在上面的例子中,我們通過以下方式達到了面試題所需的目的:

  • 設(shè)置     runtime.GOMAXPROCS 方法模擬了單核 CPU 下只有一個 P 的場景。
  • 運行一個 Goroutine,內(nèi)部跑一個 for 死循環(huán),達到阻塞運行的目的。
  • 運行一個 Goroutine,主函數(shù)(main)本身就是一個 Main Goroutine。

思考一下:這段程序是否會輸出 ”腦子進煎魚了“ 呢,為什么

答案是:

  • 在 Go1.14 前,不會輸出任何結(jié)果。
  • 在 Go1.14 及之后,能夠正常輸出結(jié)果。
 

為什么

這是怎么回事呢,這兩種情況分別對應(yīng)了什么原因和標準,Go 版本的變更有帶來了什么影響?

 

不會輸出任何結(jié)果

顯然,這段程序是有一個 Goroutine 是正在執(zhí)行死循環(huán),也就是說他肯定無法被搶占。

這段程序中更沒有涉及主動放棄執(zhí)行權(quán)的調(diào)用(runtime.Gosched),又或是其他調(diào)用(可能會導(dǎo)致執(zhí)行權(quán)轉(zhuǎn)移)的行為。因此這個 Goroutine 是沒機會溜號的,只能一直打工...

那為什么主協(xié)程(Main Goroutine)會無法運行呢,其實原因是會優(yōu)先調(diào)用休眠,但由于單核 CPU,其只有唯一的 P。唯一的 P 又一直在打工不愿意下班(執(zhí)行 for 死循環(huán),被迫無限加班)。

因此主協(xié)程永遠沒有機會唄調(diào)度,所以這個 Go 程序自然也就一直阻塞在了執(zhí)行死循環(huán)的 Goroutine 中,永遠無法下班(執(zhí)行完畢,退出程序)。

 

正常輸出結(jié)果

那為什么 Go1.14 及以后的版本,又能正常輸出了呢?

主要還是在 Go1.14 實現(xiàn)了基于信號的搶占式調(diào)度,以此來解決上述一些仍然無法被搶占解決的場景。

主要原理是Go 程序在啟動時,會在 runtime.sighandler 方法注冊并且綁定 SIGURG 信號:

func mstartm0() {
 ...
 initsig(false)
}

func initsig(preinit bool) {
 for i := uint32(0); i < _NSIG; i++ {
  ...
  setsig(i, funcPC(sighandler))
 }
}
 

綁定相應(yīng)的 runtime.doSigPreempt 搶占方法:

func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
    ...
    if sig == sigPreempt && debug.asyncpreemptoff == 0 {
        // 執(zhí)行搶占
        doSigPreempt(gp, c)
    }
}
 

同時在調(diào)度的 runtime.sysmon 方法會調(diào)用 retake 方法處理一下兩種場景:

  • 搶占阻塞在系統(tǒng)調(diào)用上的 P。
  • 搶占運行時間過長的 G。

該方法會檢測符合場景的 P,當滿足上述兩個場景之一時,就會發(fā)送信號給 M。M 收到信號后將會休眠正在阻塞的 Goroutine,調(diào)用綁定的信號方法,并進行重新調(diào)度。以此來解決這個問題。

注:在 Go 語言中,sysmon 會用于檢測搶占。sysmon 是 Go 的 Runtime 的系統(tǒng)檢測器,sysmon 可進行 forcegc、netpoll、retake 等一系列騷操作(via @xiaorui)。

在這篇文章中,我們針對 ”單核 CPU,開兩個 Goroutine,其中一個死循環(huán),會怎么樣?“ 這個問題進行了展開剖析。

針對不同 Go 語言版本,不同程序邏輯的表現(xiàn)形式都不同,但背后的基本原理都是與 Go 調(diào)度模型和搶占有關(guān)。

上述內(nèi)容就是Go語言中單核CPU開兩個Goroutine時其中一個死循環(huán)會怎么樣,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

新聞標題:Go語言中單核CPU開兩個Goroutine時其中一個死循環(huán)會怎么樣
標題網(wǎng)址:http://m.kartarina.com/article18/jeccdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站品牌網(wǎng)站設(shè)計標簽優(yōu)化移動網(wǎng)站建設(shè)Google

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管
主站蜘蛛池模板: 日日摸日日碰夜夜爽无码| 久久亚洲av无码精品浪潮| 人妻无码人妻有码中文字幕| HEYZO无码综合国产精品227| 亚洲人成影院在线无码按摩店| 精品无码人妻一区二区免费蜜桃 | 亚洲成A人片在线观看无码不卡 | 久久无码国产专区精品| 精品无码成人久久久久久 | 18精品久久久无码午夜福利| 国产成人无码精品久久二区三区| 亚洲精品无码不卡在线播HE| 久久久久久亚洲av无码蜜芽| 亚洲国产精品成人精品无码区在线| 影音先锋无码a∨男人资源站| 久久av高潮av无码av喷吹| 91精品国产综合久久四虎久久无码一级 | 日韩午夜福利无码专区a| 好硬~好爽~别进去~动态图, 69式真人无码视频免 | 国产成年无码久久久免费| 亚洲AV综合色区无码一二三区 | 无码激情做a爰片毛片AV片| 日韩精品真人荷官无码| 国产亚洲精品a在线无码| 亚洲人成国产精品无码| 无码人妻一区二区三区一| 亚洲AV无码一区东京热久久| 中文字幕无码不卡在线| 午夜寂寞视频无码专区| 中文AV人妻AV无码中文视频| 亚洲国产精品无码久久一线| 13小箩利洗澡无码视频网站免费 | 久久久精品无码专区不卡| 国产丰满乱子伦无码专| 亚洲AV色无码乱码在线观看| 亚洲国产av高清无码| 亚洲精品无码专区| 久久亚洲精品无码网站| 午夜寂寞视频无码专区| 好硬~好爽~别进去~动态图, 69式真人无码视频免 | 精品久久久久久无码中文字幕漫画 |