无锁并发访问变量
Concurrent access to variable without lock
我被一个问题打扰了,
should we add lock if only one thread write variable, and other thread just read variable?
所以我写了这样的代码来测试一下
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var lock sync.RWMutex
var i = 0
func main() {
runtime.GOMAXPROCS(2)
go func() {
for {
fmt.Println("i am here", i)
time.Sleep(time.Second)
}
}()
for {
i += 1
}
}
结果是保持打印 i am here 0
即使在第二秒之后。我对内存屏障或 cpu 缓存略知一二。但是怎么会缓存这么久呢?我想过几次后,它应该读取我已经更改过的变量。
请哪位高手go或电脑系统帮忙解答一下好吗?
Update:我知道像这样更新变量是错误的方法,我想知道为什么它在 cpu/memory 视图中未定义。
should we add lock if only one thread write variable, and other thread just read variable?
是的。总是。不争论了。
您的测试代码无法证明或反驳任何内容,因为它的行为是未定义的。
你有一场数据竞赛。因此,结果未定义。
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var lock sync.RWMutex
var i = 0
func main() {
runtime.GOMAXPROCS(2)
go func() {
for {
fmt.Println("i am here", i)
time.Sleep(time.Second)
}
}()
for {
i += 1
}
}
输出:
$ go run -race racer.go
==================
WARNING: DATA RACE
Read at 0x0000005e3600 by goroutine 6:
main.main.func1()
/home/peter/gopath/src/racer.go:17 +0x63
Previous write at 0x0000005e3600 by main goroutine:
main.main()
/home/peter/gopath/src/racer.go:22 +0x7b
Goroutine 6 (running) created at:
main.main()
/home/peter/gopath/src/racer.go:15 +0x4f
==================
i am here 3622
i am here 43165250
i am here 86147697
^Csignal: interrupt
$
参考文献:
最后,我找到了这个答案,我知道在数据竞争中你会得到一个未定义的行为,但我想知道为什么它目前的行为是这样的。
这个 snap 代码是因为编译器只是删除了 Add 函数,它从不添加。
所以我们有教训,如果你写一个未定义的行为,你可能会得到一个月亮 - -
编译器会将你的代码视为垃圾,它没有任何价值。
我被一个问题打扰了,
should we add lock if only one thread write variable, and other thread just read variable?
所以我写了这样的代码来测试一下
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var lock sync.RWMutex
var i = 0
func main() {
runtime.GOMAXPROCS(2)
go func() {
for {
fmt.Println("i am here", i)
time.Sleep(time.Second)
}
}()
for {
i += 1
}
}
结果是保持打印 i am here 0
即使在第二秒之后。我对内存屏障或 cpu 缓存略知一二。但是怎么会缓存这么久呢?我想过几次后,它应该读取我已经更改过的变量。
请哪位高手go或电脑系统帮忙解答一下好吗?
Update:我知道像这样更新变量是错误的方法,我想知道为什么它在 cpu/memory 视图中未定义。
should we add lock if only one thread write variable, and other thread just read variable?
是的。总是。不争论了。
您的测试代码无法证明或反驳任何内容,因为它的行为是未定义的。
你有一场数据竞赛。因此,结果未定义。
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var lock sync.RWMutex
var i = 0
func main() {
runtime.GOMAXPROCS(2)
go func() {
for {
fmt.Println("i am here", i)
time.Sleep(time.Second)
}
}()
for {
i += 1
}
}
输出:
$ go run -race racer.go
==================
WARNING: DATA RACE
Read at 0x0000005e3600 by goroutine 6:
main.main.func1()
/home/peter/gopath/src/racer.go:17 +0x63
Previous write at 0x0000005e3600 by main goroutine:
main.main()
/home/peter/gopath/src/racer.go:22 +0x7b
Goroutine 6 (running) created at:
main.main()
/home/peter/gopath/src/racer.go:15 +0x4f
==================
i am here 3622
i am here 43165250
i am here 86147697
^Csignal: interrupt
$
参考文献:
最后,我找到了这个答案,我知道在数据竞争中你会得到一个未定义的行为,但我想知道为什么它目前的行为是这样的。
这个 snap 代码是因为编译器只是删除了 Add 函数,它从不添加。
所以我们有教训,如果你写一个未定义的行为,你可能会得到一个月亮 - -
编译器会将你的代码视为垃圾,它没有任何价值。