面试题答案
一键面试容易引发数据竞争的场景
- 多个goroutine同时读写共享变量:当多个goroutine同时对同一个变量进行读取和写入操作,且没有适当的同步机制时,就会引发数据竞争。例如:
package main
import (
"fmt"
)
var num int
func main() {
for i := 0; i < 10; i++ {
go func() {
num = num + 1
}()
}
fmt.Println(num)
}
在这个例子中,多个goroutine同时对num
变量进行写操作,没有同步机制,可能导致数据竞争。
2. 读写操作没有正确的顺序:即使只有一个写操作,但如果读操作和写操作的顺序没有正确同步,也可能出现数据竞争。例如:
package main
import (
"fmt"
)
var flag bool
var data int
func writer() {
data = 42
flag = true
}
func reader() {
if flag {
fmt.Println(data)
}
}
func main() {
go writer()
reader()
}
在这个例子中,reader
函数依赖writer
函数设置的flag
来读取data
,但由于没有适当同步,reader
可能在data
被完全写入之前读取,导致数据竞争。
使用Go提供的工具检测数据竞争
Go提供了go build
、go run
和go test
命令的-race
标志来检测数据竞争。
- 构建时检测:在构建可执行文件时,使用
-race
标志:
go build -race main.go
- 运行时检测:在运行程序时,使用
-race
标志:
go run -race main.go
- 测试时检测:在运行测试时,使用
-race
标志:
go test -race
当检测到数据竞争时,Go会输出详细的报告,包括竞争发生的位置、涉及的goroutine等信息,帮助开发者定位和解决问题。