亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

操作系統線程是否在 go-routine 執行的 io 上被阻塞?

操作系統線程是否在 go-routine 執行的 io 上被阻塞?

Go
拉風的咖菲貓 2022-06-01 17:29:35
在我的機器上有 4 個邏輯處理器。所以有四個上下文P1, P2, P3&P4使用 OS 線程M1, M2, M3&M4$ lscpuArchitecture:        x86_64CPU op-mode(s):      32-bit, 64-bitByte Order:          Little EndianCPU(s):              4On-line CPU(s) list: 0-3Thread(s) per core:  2Core(s) per socket:  2Socket(s):           1在下面的代碼中:package mainimport (    "fmt"    "io/ioutil"    "net/http")func getPage(url string) (int, error) {    resp, err := http.Get(url)    if err != nil {        return 0, err    }    defer resp.Body.Close()    body, err := ioutil.ReadAll(resp.Body)    if err != nil {        return 0, err    }    return len(body), nil}func worker(urlChan chan string, sizeChan chan<- string, i int) {    for {        url := <-urlChan        length, err := getPage(url)        if err == nil {            sizeChan <- fmt.Sprintf("%s has length %d (%d)", url, length, i)        } else {            sizeChan <- fmt.Sprintf("%s has error %s (%d)", url, err, i)        }    }}func main() {    urls := []string{"http://www.google.com/", "http://www.yahoo.com",        "http://www.bing.com", "http://bbc.co.uk", "http://www.ndtv.com", "https://www.cnn.com/"}    urlChan := make(chan string)    sizeChan := make(chan string)    for i := 0; i < len(urls); i++ {        go worker(urlChan, sizeChan, i)    }    for _, url := range urls {        urlChan <- url    }    for i := 0; i < len(urls); i++ {        fmt.Printf("%s\n", <-sizeChan)    }}有六個執行例程http.Get()1)OS thread() 是否被io() 上M1的 go-routine() 阻塞?上下文G1http.Get()P1或者G1Go 調度程序是否會從 OS 線程(M1)搶占 go-routine( ) http.Get()?并分配G2給M1... 如果是,則在搶占 時G1,G1Goruntime如何G1在 IO() 完成后恢復http.Get?2)檢索用于每個 go-routine(G) 的上下文編號 (P) 的 api 是什么?用于調試目的..3) 我們使用 C pthreads 庫為上述讀寫器問題使用計數信號量維護關鍵部分。為什么我們不使用 go-routines 和通道來使用關鍵部分?
查看完整描述

1 回答

?
有只小跳蛙

TA貢獻1824條經驗 獲得超8個贊

不,它不會阻塞。我粗略的(并且沒有來源,我是通過 osmosis 得到的)理解是,每當一個 goroutine 想要執行一個具有等效非阻塞版本的“阻塞”I/O 時,

  1. 改為執行非阻塞版本。

  2. 將它自己的 ID 記錄在一個由它“阻塞”的句柄鍵入的表中。

  3. 將完成的責任轉移到一個專用線程,該線程位于select循環中(或poll任何可用的等效線程)等待此類操作解除阻塞,并且

  4. 掛起自身,釋放其操作系統線程(M)以運行另一個 goroutine。

當 I/O 操作解除阻塞時,選擇循環在表中查找哪個 goroutine 對結果感興趣,并安排它運行。這樣,等待 I/O 的 goroutine 就不會占用一個 OS 線程。

在無法以非阻塞方式完成的 I/O 或任何其他阻塞系統調用的情況下,goroutine 通過將其線程標記為阻塞的運行時函數執行系統調用,并且運行時將為 goroutines 創建一個新的 OS 線程以被安排在。這保持了讓 GOMAXPROCS 運行(未阻塞)goroutines 的能力。對于大多數程序來說,這不會導致太多的線程膨脹,因為用于處理文件、套接字等的最常見的系統調用已經變得異步友好。(感謝@JimB 提醒我這一點,以及有用的鏈接答案的作者。)


查看完整回答
反對 回復 2022-06-01
  • 1 回答
  • 0 關注
  • 143 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號