gpt4 book ai didi

dictionary - golang线程安全映射, channel 作为线程安全的值

转载 作者:数据小太阳 更新时间:2023-10-29 03:37:40 27 4
gpt4 key购买 nike

我用 this作为并发映射,缓冲 channel 作为线程安全的映射值(作为队列工作),当测试使用 10 个 goroutines 时,从 channel 获得的值与发送的值不同,有什么建议吗?

package main

import "fmt"
import "github.com/streamrail/concurrent-map"

func main() {
testmap := cmap.New()
fmt.Println("SyncMapNew: ", TestInParallel(&testmap, 10))
}

func TestInParallel(g *cmap.ConcurrentMap, n int) time.Duration {
start := time.Now()
var wait sync.WaitGroup

for i := 0; i < n; i++ {
wait.Add(1)
go func() {
TheTest(g, rand.New(rand.NewSource(int64(i*500))))
wait.Done()
}()
}
wait.Wait()
return time.Now().Sub(start)
}

func TheTest(g *cmap.ConcurrentMap, rnd *rand.Rand) time.Duration {
start := time.Now()
var key string
var value time.Time
for i := 0; i < 10000; i++ {
key = strconv.Itoa(int(rnd.Int31n(50000)))
if g.Has(key) == false {
g.Set(key, make(chan time.Time, 100))
}
tchan, _ := g.Get(key)
castchan := tchan.(chan time.Time)
value = time.Now()
castchan <- value
got := <-castchan
g.Set(key, castchan)
if value != got {
panic(fmt.Sprintf("ERROR: expected %v, got %v", value, got))
}
}
return time.Now().Sub(start)
}

更新我理解错了业务逻辑,代码应该是这样的

key = strconv.Itoa(int(rnd.Int31n(500)))
tchan, _ := g.GetSet(key, make(chan time.Time, 100))
castchan := tchan.(chan time.Time)
value = time.Now()
if len(castchan) >= 99 {
<-castchan//do somthing here
}
castchan <- value
g.Set(key, castchan)

最佳答案

您使用的是随 secret 钥,因此多个 goroutine 可能会获得相同的随机数。

如果两个例程在同一时间获得相同的数字,则

这是一个竞争条件:

if g.Has(key) == false {
g.Set(key, make(chan time.Time, 100))
}

有可能 h.Has 在同一时间对两个 goroutines 为 false 然后它们都设置了,所以 goroutine1 设置了 chan A,goroutine2 设置了 chan B,然后都使用了 chan B

为了解决这个问题,你需要类似的东西

SetIfAbsent

哪个锁,检查它是否存在,如果不存在,设置它,然后解锁。

您链接 map 的库作为缓存并不是非常有用,因为它不提供原子 SetIfAbsent 类型的函数。


如果没有 g.Has/g.Set 竞争,那么如果两个例程恰好获得相同的键,因此,相同的 channel ,您无法保证哪个值在队列中排在第一位,并且首先阅读。

所以 goroutine1 可能会读取 goroutine2 放入的值,反之亦然。

当考虑在并发执行系统中使用共享状态时,您必须假设任何其他操作都可能发生在任何语句/代码行之间。

我通常喜欢将其视为,您应该假设您的每一行代码一次在每个核心上运行。

因此,在 Has/Set 示例中它将是:

if g.Has(key) == false { // goroutine1
if g.Has(key) == false { // goroutine2
g.Set(key, make(chan time.Time, 100)) //goroutine1
g.Set(key, make(chan time.Time, 100)) //goroutine2
} //goroutine1
} //goroutine2
tchan, _ := g.Get(key) //goroutine1
tchan, _ := g.Get(key) //goroutine2

看看错误在哪里?第二个例程将它的 channel 放在 map 中,但两者都在 tchan 线上检索到相同的 channel 。

有道理吗?

关于dictionary - golang线程安全映射, channel 作为线程安全的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30339066/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com