golang中g(shù)o race使用
多線程/協(xié)程中的線程安全分析
在項目中,使用多線程會導致線程安全問題,引發(fā)bug發(fā)生,如果是運行中發(fā)生問題更難定位
常見的情況有兩種 死鎖 競爭,例如
死鎖
編譯打包時,死鎖發(fā)生 go run 會直接報錯
兩個或兩個以上的進程(或線程)在執(zhí)行過程中,因爭奪資源而造成的一種相互等待的現(xiàn)象。
競爭
當兩個線程競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態(tài)條件。
Go 的命令中,-race參數(shù)用于啟用競態(tài)檢測器(Race Detector)
雖然說,我們能夠通過規(guī)范的代碼避免死鎖,sync.Mutex和channel規(guī)避線程安全,但總該有個監(jiān)測的過程,以防萬一
go reac就是幫我們干這個事情的,切記,建議在測試環(huán)境中使用?。?!
它能幫助你發(fā)現(xiàn)程序中是否存在多個 goroutine 同時讀寫同一個變量而沒有同步機制的問題
使用方式例如
go test -race mypkg go run -race mysrc.go go build -race mycmd go install -race mypkg
使用示例
我們故意寫一段,線程危險的程序
package main
import (
"fmt"
"time"
)
var counter int = 0
func main() {
go func() {
for i := 0; i < 100; i++ {
counter++ // 寫操作
}
}()
go func() {
for i := 0; i < 100; i++ {
counter-- // 寫操作
}
}()
time.Sleep(10 * time.Millisecond) // 等待 goroutine 執(zhí)行(不推薦的方式,僅用于演示)
fmt.Println("Final counter:", counter)
}
使用go run -race main.go調(diào)試
這里已經(jīng)很清晰的將分析報告、代碼行數(shù)輸出
==================
WARNING: DATA RACE
Read at 0x000001d6bd90 by goroutine 7:
main.main.func2()
/Applications/www/blog-code/main.go:19 +0x2c
Previous write at 0x000001d6bd90 by goroutine 6:
main.main.func1()
/Applications/www/blog-code/main.go:13 +0x44
Goroutine 7 (running) created at:
main.main()
/Applications/www/blog-code/main.go:17 +0x33
Goroutine 6 (finished) created at:
main.main()
/Applications/www/blog-code/main.go:11 +0x27
==================
==================
WARNING: DATA RACE
Read at 0x000001d6bd90 by main goroutine:
main.main()
/Applications/www/blog-code/main.go:24 +0x77
Previous write at 0x000001d6bd90 by goroutine 7:
main.main.func2()
/Applications/www/blog-code/main.go:19 +0x44
Goroutine 7 (finished) created at:
main.main()
/Applications/www/blog-code/main.go:17 +0x33
==================
Final counter: 0
Found 2 data race(s)
exit status 66
我們將代碼修改一些,加上安全鎖
// race_fixed.go
package main
import (
"fmt"
"sync"
)
var (
counter int
mu sync.Mutex
)
func main() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
mu.Lock()
counter++
mu.Unlock()
}
}()
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
mu.Lock()
counter--
mu.Unlock()
}
}()
wg.Wait()
fmt.Println("Final counter:", counter) // 應(yīng)該輸出 0
}
再次執(zhí)行 go run -race main.go 將沒有警告輸出
Final counter: 0
注意
- 不要用于生產(chǎn)環(huán)境
- -race 會顯著降低程序性能(約 2–10 倍變慢),內(nèi)存占用也更高
- windows下需有
gcc環(huán)境,且與go的版本匹配,例如 go.1.22 使用 gcc version 8.1 會有異常發(fā)生,推薦使用 gcc14.2
到此這篇關(guān)于golang中g(shù)o race使用的文章就介紹到這了,更多相關(guān)go race使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang 處理浮點數(shù)遇到的精度問題(使用decimal)
本文主要介紹了Golang 處理浮點數(shù)遇到的精度問題,不使用decimal會出大問題,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02

