并发访问无锁变量

问题描述:

I was disturbed by a question,

should we add lock if only one thread write variable, and other thread just read variable?

so I write such code to test it

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
    }
}

The result is keep print i am here 0 even after second of time. I know a little about Memory barrier or cpu cache. but how could it be cache for such a long time? I think after a few time, it should read variable I already changed.

Can anyone who is master go or computer system could help answer, please?


Update: i know it is a wrong way to update variable like this, i want to know why it is undefined in cpu/memory view.

我被一个问题困扰, p>

如果只有一个线程写入变量,而另一个线程只是读取变量,我们会加锁? p> blockquote>

所以我编写了这样的代码进行测试 p>

 包main 
 
import(
“ fmt” 
“ runtime” 
“ sync” 
“ time” 
)
 
var锁定同步。RWMutex
var i = 0 \  n 
func main(){
 runtime.GOMAXPROCS(2)
 go func(){
 for {
 fmt.Println(“ i am here”,i)
 time.Sleep(time.Second)  
} 
}()
为{
i + = 1 
} 
} 
  code>  pre> 
 
 

结果是保持打印 i am 这里是0 code>,甚至是第二秒之后。 我对内存屏障或cpu缓存有所了解。 但是怎么会这么长时间缓存呢? 我想过一会儿,它应该读取我已经更改过的变量。 p>

任何一个熟练掌握或计算机系统的人都可以帮忙回答吗? p>


更新 strong>:我知道这样更新变量是错误的方式,我想知道为什么在cpu中未定义它 /内存视图。 p> div>

finally, i find this answers, i know with a data race you will get a undefined behave, but i want to know why it behave like that currently.

this snap code is because complier just remove Add function, it never add.

so we have lesson, if you write a undefined behave, you may got a moon - -

complier will treat you code as rubbish, it does not have any value.

should we add lock if only one thread write variable, and other thread just read variable?

Yes. Always. No arguing here.

Your test code proves and disproves nothing as its behaviour is undefined.

You have a data race. Therefore, the results are undefined.

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
    }
}

Output:

$ 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
$

References:

Data Race Detector

Benign Data Races: What Could Possibly Go Wrong?