根据Go博客,
映射对于并发使用是不安全的:它没有定义当您同时读取和写入时会发生什么.如果您需要从同时执行的goroutine中读取和写入映射,则访问必须由某种同步机制调解.(来源:https://blog.golang.org/go-maps-in-action)
任何人都可以详细说明这个吗?并发读取操作在例程中似乎是允许的,但是如果尝试读取和写入相同的键,则并发读/写操作可能会生成竞争条件.
在某些情况下可以降低最后的风险吗?例如:
这不是代码(显然),但我认为它显示了一个案例的轮廓,即使A和B都试图访问m,也不会出现竞争条件,或者如果有的话也无关紧要因为额外的限制.
当我查看golang内存模型文档(链接)时,我在go lang上发现了一个奇怪的行为.该文档说下面的代码可能发生g打印2然后0.
var a, b int
func f() {
a = 1
b = 2
}
func g() {
print(b)
print(a)
}
func main() {
go f()
g()
}
Run Code Online (Sandbox Code Playgroud)
这只是常规问题吗?因为我很好奇为什么变量'b'的值赋值可以在'a'之前发生?即使'a'和'b的值赋值将在不同的线程中发生(不在主线程中),是否必须确保'a'应该在它自己的线程中的'b'之前分配?(因为赋值' '先到先得'和'b'先出现了)有谁能清楚告诉我这个问题?
就像在这里我创建了一个游乐场样本:sGgxEh40ev,但无法让它工作.
quit := make(chan bool)
res := make(chan int)
go func() {
idx := 0
for {
select {
case <-quit:
fmt.Println("Detected quit signal!")
return
default:
fmt.Println("goroutine is doing stuff..")
res <- idx
idx++
}
}
}()
for r := range res {
if r == 6 {
quit <- true
}
fmt.Println("I received: ", r)
}
Run Code Online (Sandbox Code Playgroud)
输出:
goroutine is doing stuff..
goroutine is doing stuff..
I received: 0
I received: 1
goroutine is doing stuff..
goroutine is …Run Code Online (Sandbox Code Playgroud) 我知道golang bytes.Buffer不是线程安全的,但如果我有一个作家(在goroutine中)和一个读者(在另一个goroutine中).安全吗?
如果没有,那为什么不呢?写操作从读取开始读取时附加到缓冲区,因此我没有看到它们将访问相同内存位置的情况.
concurrentMap()函数Have WARNING: DATA RACE和致命错误:concurrent map read and map write
concurrentStruct() 有警告:数据竞赛,但运行正常
package main
import (
"sync"
)
func main() {
// concurrentMap()
concurrentStruct()
// concurrentStructWithMuLock()
}
type Metadata struct {
mu sync.RWMutex //
key bool
}
// concurrentStruct ???????
// concurrent read and write the struct
// go run -race main.go ? WARNING: DATA RACE???????
// go run -race main.go It have WARNING: DATA RACE, But running ok
func concurrentStruct() {
m := …Run Code Online (Sandbox Code Playgroud) 我有一段来自这个网站的代码,它对对象的初始化进行了双重检查锁定。
func checkSyncProducer() {
mutex.RLock()
if syncProducer == nil {
mutex.RUnlock()
mutex.Lock()
defer mutex.Unlock()
if syncProducer == nil {
syncProducer = createSyncKafkaProducer() //this func will initialize syncProducer.
}
} else {
defer mutex.RUnlock()
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码mutex.RLock()在第一个 nil 检查之前。
为什么需要这样做?(它在页面中进行了解释,但我无法理解)并且它不会增加开销,因为每次调用 checkSyncProducer 时都会获取和释放读锁。
在获取读锁之前是否应该再进行一次 nil 检查,例如:
func checkSyncProducer() {
if syncProducer == nil {
mutex.RLock()
if syncProducer == nil {
mutex.RUnlock()
mutex.Lock()
defer mutex.Unlock()
if syncProducer == nil {
createSyncKafkaProducer()
}
} else {
defer mutex.RUnlock()
}
} …Run Code Online (Sandbox Code Playgroud) 最近,我学会了-race检查go中比赛条件是否存在的选项。完整的命令是go run -race xxx.go它确实对我有很大帮助。但是和下面的代码一样,我认为检查结果是错误的,并尝试了很多方法(我在下面尝试引起恐慌)导致真正的恐慌但失败了。所以,我想知道是否该代码是正确的,比赛检查是错了吗?或者你可以修改我的代码,这样我可以查阅一个真正的恐慌。非常感谢。
package main
import "fmt"
type myType struct {
A int
}
func main(){
c:=make(chan bool)
x := new(myType)
go func(){
x = new(myType) // write to x
c <- true
}()
_ = *x // read from x
<-c
fmt.Println("end")
}
Run Code Online (Sandbox Code Playgroud)
go run -race test.go
==================
WARNING: DATA RACE
Write at 0x00c00009c010 by goroutine 6:
main.main.func1()
/Users/yaodongen/test.go:12 +0x56
Previous read at …Run Code Online (Sandbox Code Playgroud) 有人告诉我memCacheInstance有竞争条件,但go run -race不知道。
代码:
type MemCache struct {
data []string
}
var memCacheInstance *MemCache
var memCacheCreateMutex sync.Mutex
func GetMemCache() *MemCache {
if memCacheInstance == nil {
memCacheCreateMutex.Lock()
defer memCacheCreateMutex.Unlock()
if memCacheInstance == nil {
memCacheInstance = &MemCache{
data: make([]string, 0),
}
}
}
return memCacheInstance
}
Run Code Online (Sandbox Code Playgroud) 代码如下:
m := make(map[interface{}]interface{})
//read
for i := 0; i< 10000; i++ {
go func() {
for range m {
}
}()
}
//write
for i := 0; i< 10000; i++ {
go func() {
mTemp := make(map[interface{}]interface{})
m = mTemp
}()
}
Run Code Online (Sandbox Code Playgroud)
有10000个读goroutine访问m,另外10000个写goroutine为m分配一个新的map,安全吗?
I'm learning concurrency-related issues in Golang. I wrote some code:
package main
import (
"fmt"
"time"
)
func incr(num *int) {
*num = *num + 1
}
func main() {
var a = 0
for i := 0; i < 50; i++ {
go incr(&a)
}
incr(&a)
time.Sleep(1 * time.Second)
fmt.Println(a)
}
Run Code Online (Sandbox Code Playgroud)
The result of this code is: 51
In this code I've declared a variable which I'm increasing in 50 running goroutines. What I've read and unsterstood this code …