2 回答

TA貢獻1828條經驗 獲得超3個贊
簡單地使用https://eli.thegreenplace.net/2019/on-concurrency-in-go-http-servers/中的示例可以構建一個簡單的示例,表明它并不安全。
使用一個簡單的程序,如:
package main
import (
"net/http"
)
func main() {
counters := map[string]int{}
name := "test"
counters[name] = 0
http.HandleFunc("/test", func(w http.ResponseWriter, req *http.Request) {
counters[name]++
})
http.ListenAndServe(":8000", nil)
}
并刺激使用:
ab -n 20000 -c 200 "127.0.0.1:8000/test"
產生異常,如:
goroutine 158 [running]:
runtime.throw({0x64d95a, 0x81faa0})
/usr/local/go/src/runtime/panic.go:1198 +0x71 fp=0xc000384980 sp=0xc000384950 pc=0x4348f1
runtime.mapaccess2_faststr(0x697360, 0xc0003a4ba0, {0x644851, 0x4})
/usr/local/go/src/runtime/map_faststr.go:116 +0x3d4 fp=0xc0003849e8 sp=0xc000384980 pc=0x413d34
main.main.func1({0x69bf00, 0xc0003a4b60}, 0x0)
/home/test/gohttp/main.go:13 +0x46 fp=0xc000384a48 sp=0xc0003849e8 pc=0x5eba86
net/http.HandlerFunc.ServeHTTP(0x0, {0x69bf00, 0xc0003a4b60}, 0x0)

TA貢獻1775條經驗 獲得超8個贊
如果您只閱讀,那是安全的。
如果你需要寫,你需要一些方法來做到“線程安全”
第一個想法是使用 sync.Mutex 來保護對地圖的訪問
然而,這可能成為瓶頸,因為您可能有多個并行請求,但每次只能寫入一個。我們談論的是納秒……
第二種方法可以使用讀/寫互斥鎖來控制讀寫。許多 goroutines 可以讀取,但每次只有一個可以寫入。
包同步和同步/原子還有其他選項。
還有一種額外的方法需要考慮:如果你只需要寫入這個地圖,你可以考慮使用緩沖通道發送一個鍵/值結構,以便在單個 goroutine 中使用(負責將它存儲到地圖中)
如您所見,如果對您的應用程序有意義,這種方法有很多優點。
您甚至可以使用通道通過回調來安全讀/寫,但這是另一回事了。
如果您有疑問,請編寫單元測試并使用競爭條件檢測器
- 2 回答
- 0 關注
- 126 瀏覽
添加回答
舉報