Go 性能优化之race实战
一、前言
一般并发的bug 有两种,死锁(block)和 竞争(race)
- 死锁发生时,go run 会直接报错
- race 发生时,要加race 才会在运行时报warning
二、race基础
2.1 race 使用方式
go test -race mypkg // test the package
go run -race mysrc.go // compile and run the program
go build -race mycmd // build the command
go install -race mypkg // install the package
PS:race会在只能在运行时触发,在启用情况下其CPU和内存通常是正常程序的5~10倍,故生产环境不宜使用。
2.2 死锁和竞争的区别
- deadlock:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种相互等待的现象。
- race:当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。
2.3 如何解决竞态
- 使用sync.Mutex
- 使用channel
注意:竞态除了存在于进程内,还存在于进程间,故需要分布式锁(需要了解分布式锁原理)。
三、race分析
3.1 代码示例
package main
import "time"
func main(){
var x int
go func(){
for{
x=1
}
}()
go func(){
for{
x=2
}
}()
time.Sleep(100*time.Second)
}
3.2 运行命令
go run xxx.go 后面加上 -race 参数
运行结果如下:
$ go run -race race.go
==================
WARNING: DATA RACE
Write at 0x00c0000a2000 by goroutine 6:
main.main.func2()
/Users/harryhare/git/go_playground/src/race.go:15 +0x38
Previous write at 0x00c0000a2000 by goroutine 5:
main.main.func1()
/Users/harryhare/git/go_playground/src/race.go:9 +0x38
Goroutine 6 (running) created at:
main.main()
/Users/harryhare/git/go_playground/src/race.go:13 +0x9c
Goroutine 5 (running) created at:
main.main()
/Users/harryhare/git/go_playground/src/race.go:7 +0x7a
==================
四、总结
- race 和 单例没有关系,也检测不出来。
- race 只是解决读写不一致的现场,出现同时读写的现象。