go - 在读取和修改之前锁定 slice

我最近使用 Go 的经验,在审查一些代码时,我发现虽然它被写保护,但读取数据时存在问题。不是读取本身,而是读取和修改 slice 之间可能发生的修改。

type ConcurrentSlice struct {
    sync.RWMutex
    items []Item
}

type Item struct {
    Index int
    Value Info
}

type Info struct {
    Name        string 
    Labels      map[string]string
    Failure     bool

}

如前所述,写作以这种方式受到保护:


func (cs *ConcurrentSlice) UpdateOrAppend(item ScalingInfo) {
    found := false
    i := 0
    for inList := range cs.Iter() {
        if item.Name == inList.Value.Name{
            cs.items[i] = item
            found = true
        }
        i++
    }
    if !found {
        cs.Lock()
        defer cs.Unlock()

        cs.items = append(cs.items, item)
    }
}

func (cs *ConcurrentSlice) Iter() <-chan ConcurrentSliceItem {
    c := make(chan ConcurrentSliceItem)

    f := func() {
        cs.Lock()
        defer cs.Unlock()
        for index, value := range cs.items {
            c <- ConcurrentSliceItem{index, value}
        }
        close(c)
    }
    go f()

    return c
}

但是在收集 slice 的内容和修改它之间,可能会发生修改。可能是另一个例程修改了同一个 slice ,当该赋值时,它已经不存在了:slice[i ] = 项目

处理这个问题的正确方法是什么?

我已经实现了这个方法:

func GetList() *ConcurrentSlice {
    if list == nil {
        denylist = NewConcurrentSlice()
        return denylist
    }
    return denylist
}

我是这样使用它的:

concurrentSlice := GetList()
concurrentSlice.UpdateOrAppend(item)

但我知道在获取和修改之间,即使它实际上是立即的,另一个例程也可能修改了 slice 。以原子方式执行这两个操作的正确方法是什么?我阅读的 slice 100% 是我修改的 slice 。因为如果我尝试将一个项目分配给一个不再存在的索引,它会中断执行。

提前致谢!

最佳答案

您进行阻止的方式是不正确的,因为它不能确保您退回的元素没有被移除。在更新的情况下,数组仍将至少保持相同的长度。

一个更简单的可行解决方案如下:

func (cs *ConcurrentSlice) UpdateOrAppend(item ScalingInfo) {
    found := false
    i := 0
    cs.Lock()
    defer cs.Unlock()

    for _, it := range cs.items {
        if item.Name == it.Name{
            cs.items[i] = it
            found = true
        }
        i++
    }
    if !found {
        cs.items = append(cs.items, item)
    }
}

https://stackoverflow.com/questions/73859360/

相关文章:

python - 在代表 python 中大文件的大字符串上加速 re.sub()?

regex - 为什么 Perl 正则表达式不匹配 "\n"和后面的字符?

haskell - 我可以在 Haskell 中将数字全局限制为只有 3 位小数吗?

c++ - 如何在始终选择第一个元素并过滤其余元素的范围内创建 View ?

r - 识别/描述向量中具有特定值的连续几天的序列

c++ - 我可以继承 std::array 并重载 operator [] 吗?

typescript - 为什么 `type T1 = undefined & {}` 从不出现在

regex - 包含至少两个数字/字母的序列的 Python 正则表达式

bash - 使用 sed 删除算术形式

rust - -1 和 pow 的特殊行为