golang竞态检测

背景

  • 在阅读golang runtime相关代码时,发现有个变量raceenabled,于是查了下文档了解了下

具体案例

  • 了解raceenabled前,先看这么段代码
package main

import (
	"fmt"
	"sync"
)

var x int = 0

func Add(y int) {
	x = x + y
}

func Race() {
	var wg sync.WaitGroup

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			Add(10)
		}()
	}

	wg.Wait()

	fmt.Println(x)
}

func NoRace() {
	for i := 0; i < 1000; i++ {
		Add(10)
	}

	fmt.Println(x)
}

func main() {
	Race()
	NoRace()
}
  • 很显然,Race()函数存在竞态问题,多个协程同时在修改变量x,最后输出的x值也不是+10000的结果
  • 而NoRace()就不会有这种问题
$ go run race1.go 
8480
18480
  • 因为代码逻辑比较简单,所以一眼就能看出问题
  • 但如果是一个复杂的工程项目,某个变量存在竞态行为,光靠肉眼排查比较低效,这时候竞态检测就派上用场了
  • 如何开启竞态检测:
$ 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
  • 按照官方文档,加上-race参数即可
  • 此时,raceenabled就会被置为true,编译器通过代码记录所有内存访问,包括内存是什么时候、怎样被访问的
  • 这样代码中的竞态行为,就会在运行时被捕获:
$ go run -race race1.go 
==================
WARNING: DATA RACE
Read at 0x000000646f80 by goroutine 8:
  main.Add()
      /home/zhangsan/myGoTest/race1.go:11 +0x6f
  main.Race.func1()
      /home/zhangsan/myGoTest/race1.go:21 +0x5f

Previous write at 0x000000646f80 by goroutine 7:
  main.Add()
      /home/zhangsan/myGoTest/race1.go:11 +0x8b
  main.Race.func1()
      /home/zhangsan/myGoTest/race1.go:21 +0x5f

Goroutine 8 (running) created at:
  main.Race()
      /home/zhangsan/myGoTest/race1.go:19 +0xab
  main.main()
      /home/zhangsan/myGoTest/race1.go:39 +0x2f

Goroutine 7 (finished) created at:
  main.Race()
      /home/zhangsan/myGoTest/race1.go:19 +0xab
  main.main()
      /home/zhangsan/myGoTest/race1.go:39 +0x2f
==================
9970
19970
Found 1 data race(s)
exit status 66

局限性

  • 开启了竞态检测,必然会有额外的开销:10倍的CPU、内存开销。。。
  • 所以在线上环境运行带竞态检测的代码,出于性能考虑,肯定是不行的
  • 但为了检测潜在的竞态行为,官方文档给的建议是:
    • 在测试环境部署带竞态检测的代码,以及负载测试、集成测试环境下
    • 在线上多节点环境下,可以选择一个节点,部署带竞态检测的代码

参考文献

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值