為什麼Go 中會出現檔案寫入阻塞的最小執行緒建立
在Go 中,當goroutine 進行阻塞呼叫時,通常會進行阻塞呼叫時,通常會進行阻塞呼叫時,通常會進行阻塞呼叫時,通常會進行阻塞呼叫時,通常會進行阻塞呼叫時,通常會進行阻塞調用建立線程促進此類操作。然而,當多個 goroutine 在嘗試寫入檔案時被阻塞時,會出現令人費解的現象。儘管存在大量 goroutine,但建立的線程數量有限。
測試程式碼和觀察
以下測試腳本示範了此行為:
package main import ( "io/ioutil" "os" "runtime" "strconv" ) func main() { runtime.GOMAXPROCS(2) data, err := ioutil.ReadFile("./55555.log") if err != nil { println(err) return } for i := 0; i < 200; i++ { go func(n int) { for { err := ioutil.WriteFile("testxxx"+strconv.Itoa(n), []byte(data), os.ModePerm) if err != nil { println(err) break } } }(i) } select {} }
諷刺的是,當執行這個腳本時,只創建了少數線程,如命令:
$ cat /proc/9616/status | grep -i thread Threads: 5
解決難題
理解此行為的關鍵在於阻塞操作的本質。在原始測試中,檔案寫入完成得太快,無法觸發新執行緒的建立。
為了說明這一點,修改了測試腳本以寫入更大的資料區塊:
package main import ( "io/ioutil" "os" "runtime" "strconv" ) func main() { runtime.GOMAXPROCS(2) data := make([]byte, 128*1024*1024) for i := 0; i < 200; i++ { go func(n int) { for { err := ioutil.WriteFile("testxxx"+strconv.Itoa(n), []byte(data), os.ModePerm) if err != nil { println(err) break } } }(i) } select {} }
此修改導致創建了超過 200個線程,如命令:
$ cat /proc/17033/status | grep -i thread Threads: 203
結論
因此,當快速執行檔案寫入操作時,調用的阻塞性質可能不足以觸發創建多個線程。只有當阻塞操作變得更加嚴重時,對額外執行緒的需求才會變得明顯,從而導致執行緒如預期的那樣激增。
以上是當許多 Goroutine 阻塞快速文件寫入時,為什麼 Go 會創建很少的線程?的詳細內容。更多資訊請關注PHP中文網其他相關文章!