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