なぜ検出器は、次のコード文句golangレース:私は-race
で、私は次の警告を取得しています上記のコードを実行するとデータレース値によって渡された構造体の値からフィールドを読み取るときに
package main
import (
"fmt"
"sync"
)
type Counter struct {
value int
mtx *sync.Mutex
}
func NewCounter() *Counter {
return &Counter {0, &sync.Mutex{}}
}
func (c *Counter) inc() {
c.mtx.Lock()
c.value++
c.mtx.Unlock()
}
func (c Counter) get() int {
c.mtx.Lock()
res := c.value
c.mtx.Unlock()
return res
}
func main() {
var wg sync.WaitGroup
counter := NewCounter()
max := 100
wg.Add(max)
// consumer
go func() {
for i := 0; i < max ; i++ {
value := counter.get()
fmt.Printf("counter value = %d\n", value)
wg.Done()
}
}()
// producer
go func() {
for i := 0; i < max ; i++ {
counter.inc()
}
}()
wg.Wait()
}
:
==================
WARNING: DATA RACE
Read at 0x00c0420042b0 by goroutine 6:
main.main.func1()
main.go:39 +0x72
Previous write at 0x00c0420042b0 by goroutine 7:
main.(*Counter).inc()
main.go:19 +0x8b
main.main.func2()
main.go:47 +0x50
Goroutine 6 (running) created at:
main.main()
main.go:43 +0x167
Goroutine 7 (running) created at:
main.main()
main.go:49 +0x192
==================
func (c Counter) get() int
をfunc (c *Counter) get() int
に変更すると、すべて正常に動作しています。 get()
の受信機タイプはポインタでなければなりません。私はなぜそれが混乱しているのですか?私は "-copylocks"を認識していますが、この場合、mtx
は値ではなくポインタです。
sync.Mutex`が含まれて私は 'MTX' を変更した場合、私はこの警告を取得main.go:23:値を通過するが、ロックを取得:main.Counterは
vet -copylocks
と値と実行プログラムを可能にします
それは理にかなっています。
注:この質問は、スレッドセーフカウンタ