有一段 Go 的代码报了 race,但不知道会有什么潜在问题,各位大佬帮忙指点一下

2019-07-05 19:11:58 +08:00
 PureWhiteWu

代码如下:

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
3491 次点击
所在节点    Go 编程语言
5 条回复
fork
2019-07-05 19:41:17 +08:00
把 mutex 去了,
用 atomic.StoreInt32(&n, 0) 代替 n = 0
用 atomic.AddInt32(&n, -1) 代替 n -= 1
100knights
2019-07-05 22:02:23 +08:00
为啥你修改要用读锁?
liulaomo
2019-07-05 22:33:59 +08:00
这写法看着真别扭。很明显第一个协程和第三第四个有竞争。
按照你这种写法,你可以把第一个和第二个一样加个读锁。
whoami9894
2019-07-05 23:06:58 +08:00
为什么原子操作还加锁
reus
2019-07-06 00:19:17 +08:00
要么全部用锁,要么全部用原子操作,混用就是 race 啊

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/580429

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX