Golang Go语言中有一段代码报了 race,但不知道会有什么潜在问题,各位大佬帮忙指点一下
Golang Go语言中有一段代码报了 race,但不知道会有什么潜在问题,各位大佬帮忙指点一下
代码如下:
package main
import (
"sync"
"sync/atomic"
)
func main() {
var n int32
var m sync.RWMutex
go func() {
for {
atomic.LoadInt32(&n)
}
}()
go func() {
for {
m.RLock()
atomic.AddInt32(&n, 1)
m.RUnlock()
}
}()
go func() {
for {
m.Lock()
n = 0
m.Unlock()
}
}()
go func() {
for {
m.Lock()
n -= 1
m.Unlock()
}
}()
// do something to keep goroutines running here
......
}
playground link: https://play.golang.org/p/Mrdetw46mXR
race 内容:
$ go run -race main.go
==================
WARNING: DATA RACE
Write at 0x00c000096000 by goroutine 7:
main.main.func3()
/Users/purewhite/go/src/xxx/main.go:26 +0x46
Previous read at 0x00c000096000 by goroutine 5:
sync/atomic.LoadInt32()
/usr/local/Cellar/go/1.12.6/libexec/src/runtime/race_amd64.s:206 +0xb
main.main.func1()
/Users/purewhite/go/src/xxx/main.go:13 +0x38
Goroutine 7 (running) created at:
main.main()
/Users/purewhite/go/src/xxx/main.go:23 +0x115
Goroutine 5 (running) created at:
main.main()
/Users/purewhite/go/src/xxx/main.go:11 +0xbd
Found 1 data race(s)
exit status 66
更多关于Golang Go语言中有一段代码报了 race,但不知道会有什么潜在问题,各位大佬帮忙指点一下的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
为啥你修改要用读锁?
这写法看着真别扭。很明显第一个协程和第三第四个有竞争。
按照你这种写法,你可以把第一个和第二个一样加个读锁。
为什么原子操作还加锁
要么全部用锁,要么全部用原子操作,混用就是 race 啊
在Go语言中,遇到race
(数据竞争)问题通常意味着你的程序在并发环境下存在多个goroutine同时访问(读或写)同一个变量,且至少有一个访问是写操作,但这些访问没有被正确地同步。数据竞争会导致未定义行为,包括但不限于:
- 数据不一致:多个goroutine可能看到同一个变量的不同值,导致程序逻辑错误。
- 程序崩溃:由于并发访问导致的内存访问冲突,程序可能会崩溃。
- 死锁:如果使用了不当的锁机制尝试解决数据竞争,可能会导致死锁,使得程序无法继续执行。
解决数据竞争的关键在于确保所有对共享变量的访问都是安全的。这通常通过以下几种方式实现:
- 使用互斥锁(sync.Mutex):保护对共享变量的访问,确保同一时间只有一个goroutine可以访问。
- 使用通道(channel):通过通道在goroutine之间传递数据,避免直接共享变量。
- 使用原子操作(sync/atomic包):对于简单的计数器等场景,可以使用原子操作来确保并发安全。
建议使用Go的race detector
工具来定位具体的数据竞争位置。在运行程序时添加-race
标志,如go run -race your_program.go
,它会帮助你找到并修复代码中的竞争条件。
总之,解决数据竞争是确保Go程序并发安全的关键,务必认真对待并彻底修复。