3 回答

TA貢獻1966條經驗 獲得超4個贊
goroutine 是一個輕量級線程,它不等同于操作系統線程。的語言規范指定它作為一個“相同的地址空間內的控制的獨立并發線程”。
引用 package 的文檔runtime
:
GOMAXPROCS 變量限制了可以同時執行用戶級 Go 代碼的操作系統線程的數量。代表Go代碼在系統調用中可以阻塞的線程數沒有限制;這些不計入 GOMAXPROCS 限制。
僅僅因為您啟動了 200 個 goroutine,并不意味著將為它們啟動 200 個線程。您設置GOMAXPROCS
為 2,這意味著可以同時運行 2 個“活動”goroutine。如果 goroutine 被阻塞(例如 I/O 等待),可能會產生新線程。你沒有提到你的測試文件有多大,你開始的 goroutines 可能寫得太快了。
在有效圍棋博客文章將它們定義為:
它們被稱為goroutines是因為現有的術語——線程、協程、進程等——傳達了不準確的內涵。goroutine 有一個簡單的模型:它是一個與同一地址空間中的其他 goroutine 并發執行的函數。它是輕量級的,成本比分配堆棧空間多一點。并且堆棧開始時很小,因此它們很便宜,并且通過根據需要分配(和釋放)堆存儲來增長。
Goroutines 被多路復用到多個 OS 線程上,所以如果一個應該阻塞,例如在等待 I/O 時,其他人繼續運行。它們的設計隱藏了線程創建和管理的許多復雜性。

TA貢獻1871條經驗 獲得超8個贊
該問題4056只討論如何限制創建實際的線程(未夠程)的數量。
Go 1.2 在commit 665feee 中引入了線程限制管理。
您可以看到一個測試,以檢查是否實際達到了創建的線程數pkg/runtime/crash_test.go#L128-L134:
func TestThreadExhaustion(t *testing.T) {
output := executeTest(t, threadExhaustionSource, nil)
want := "runtime: program exceeds 10-thread limit\nfatal error: thread exhaustion"
if !strings.HasPrefix(output, want) {
t.Fatalf("output does not start with %q:\n%s", want, output)
}
}
同一個文件有一個創建實際線程的示例(對于給定的 goroutine),使用runtime.LockOSThread():
func testInNewThread(name string) {
c := make(chan bool)
go func() {
runtime.LockOSThread()
test(name)
c <- true
}()
<-c
}

TA貢獻1825條經驗 獲得超6個贊
我稍微修改了你的程序以輸出一個更大的塊
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
所以我認為系統調用在您的原始測試中退出得太快,無法顯示您期望的效果。
- 3 回答
- 0 關注
- 541 瀏覽
添加回答
舉報