Golang并发访问固定大小的map/array

2024-03-08

我正在探索使用固定键并发访问地图而无需锁定的可能性,以提高性能。 我之前已经探索过与 slice 类似的功能,并且似乎它有效:

func TestConcurrentSlice(t *testing.T) {
    fixed := []int{1, 2, 3}
    wg := &sync.WaitGroup{}
    for i := 0; i < len(fixed); i++ {
        idx := i
        wg.Add(1)
        go func() {
            defer wg.Done()
            fixed[idx]++
        }()
    }
    wg.Wait()
    fmt.Printf("%v\n", fixed)
}

上面的代码将通过-race测试。

这让我有信心用固定大小(固定数量的键)的地图实现同样的事情,因为我假设如果键的数量不改变,那么下划线数组(在地图中)不需要扩展,所以它我们在不同的 go 例程中访问不同的密钥(不同的内存位置)将是安全的。所以我写了这个测试:

type simpleStruct struct {
    val int
}

func TestConcurrentAccessMap(t *testing.T) {
    fixed := map[string]*simpleStruct{
        "a": {0},
        "b": {0},
    }
    wg := &sync.WaitGroup{}
    // here I use array instead of iterating the map to avoid read access
    keys := []string{"a", "b"}
    for _, k := range keys {
        kcopy := k
        wg.Add(1)
        go func() {
            defer wg.Done()
            // this failed the race test
            fixed[kcopy] = &simpleStruct{}

            // this actually can pass the race test!
            //fixed[kcopy].val++
        }()
    }
    wg.Wait()
}

但是,该测试未能通过运行时测试,并出现错误消息并发写入。

我发现的一个更有趣的是我注释掉的代码“fixed[kcopy].val++”实际上通过了竞赛测试(我认为这是因为写入的内容位于不同的内存位置)。但我想知道既然 go 例程正在访问地图的不同键,为什么它会在比赛测试中失败?


访问不同的不需要多个 goroutine 同步的切片元素是可以的,因为每个切片元素都充当单独的变量。详细信息请参见我可以同时写入不同的切片元素吗 https://stackoverflow.com/questions/49879322/can-i-concurrently-write-different-slice-elements/49879469#49879469.

然而,地图的情况并非如此。特定键的值不充当变量,并且不可寻址(因为存储该值的实际内存空间可能会在内部更改 - 由实现自行决定)。

因此,对于映射,适用一般规则:如果从多个 goroutine 访问映射,其中至少有一个是写入(为键分配值),则需要显式同步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang并发访问固定大小的map/array 的相关文章

  • C# 中字典的内存使用情况

    我有一些代码添加了嵌套字典 格式如下 Dictionary
  • ConcurrentHashMap 内部是如何工作的?

    我正在阅读有关 Java 并发性的 Oracle 官方文档 我想知道Collection由返回 public static
  • 本地 Postgres 实例和 Azure Cloud Postgres 实例之间的实时同步

    我需要在本地 postgresql 实例与云 postgresql 实例之间设置实时同步过程 请让我知道我可以通过哪些选项来实现它 我是否必须使用任何特定工具或者可以通过复制进行管理 请指教 使用 PgPool http www pgpoo
  • 如何将 Unicode 字符转换为简单形式? [复制]

    这个问题在这里已经有答案了 有没有一个Go库可以Sj str m作为输入和返回Sjostrom作为输出 您可以使用golang org x text unicode norm来处理这个问题 package main import fmt i
  • Java 中的无锁并发链表

    我想使用像中描述的链接列表this http reference kfupm edu sa content l o lock free linked lists using compare and 3368 pdf纸 但是 我在网上没有找到
  • JAVA:如何搜索地图?

    我有一个 Map 其键为字符串 其值为集合 包含整数 假设我的钥匙看起来像 苹果 香蕉 橙色 等 用户输入文本 我将其保存为字符串变量 如何在我的地图中搜索相同的密钥 因此 如果用户输入 apple 我如何将该字符串提供给方法并让该方法在我
  • rsync 可以支持一对多同步吗?

    我可以在数百个网站上同步我所工作的 模型 网站的更改吗在同一台服务器上 using rsync 我会更新通用模板文件和 JS 脚本 如果可能的话我该如何设置 我在 Hostgator 专用服务器上 运行 Apache 请阅读我对下面已编辑问
  • python:查找围绕某个 GPS 位置的圆的 GPS 坐标的优雅方法

    我有一组以十进制表示的 GPS 坐标 并且我正在寻找一种方法来查找每个位置周围半径可变的圆中的坐标 这是一个例子 http green and energy com downloads test circle html我需要什么 这是一个圆
  • 使用连接池后如何处理过多的并发连接?

    Scenario 假设您有一个拥有大量流量的网站或应用程序 即使使用数据库连接池 性能也会受到真正的打击 站点 应用程序甚至可能崩溃 因为并发连接太多 Question 人们有什么选择来处理这个问题 我的想法 我在想有这个问题的人可以创建多
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 直接从一个通道发送到另一个通道

    当从一个通道直接发送到另一个通道时 我偶然发现了令人惊讶的行为 package main import fmt func main my chan make chan string chan of chans make chan chan
  • Pygame - 使用 SurfArray 将某种颜色的像素重新着色为另一种颜色(数组切片问题)

    我正在尝试为游戏制作调色板交换功能 并且正在尝试找到一种将某种颜色的像素颜色更改为另一种颜色的方法 我已经能够使用我在教程中找到的这个函数使所有像素具有相同的颜色 def color surface self surface red gre
  • 无法理解 Java 地图条目集

    我正在看一个 java 刽子手游戏 https github com leleah EvilHangman blob master EvilHangman java https github com leleah EvilHangman b
  • 使用 MPI 的 Allreduce 对 Python 对象求和

    我正在使用使用 Python 中的字典和计数器构建的稀疏张量数组操作 我想让并行使用这个数组操作成为可能 最重要的是 我最终在每个节点上都有计数器 我想使用 MPI Allreduce 或另一个不错的解决方案 将其添加在一起 例如 使用计数
  • 在 Visual Studio Code 中调试 Go 测试

    在我的 Windows 计算机上 我安装了 Visual Studio Code 要手动运行测试 我进入控制台到项目文件夹并输入 go test main test go 它工作完美 但我遇到一种情况 我需要调试我的测试以了解发生了什么 为
  • 改变字符串颜色

    好的 这是我上一个问题的延续 但我有代码 private void btnTrans Click object sender EventArgs e var abrvStr inputBx Text foreach var kvp in d
  • 如何修复“缺少表的 FROM 子句条目”错误

    我正在尝试根据游戏 ID 获取平台名称 我有如下三个表 我正在尝试加入它们以获得所需的结果 Games Id 1 2 3 4 Game Platforms Id game id platform id 1 1 1 2 1 2 3 3 3
  • 定义 types.Dict 和 dict 之间的区别?

    我正在练习使用 Python 3 5 中的类型提示 我的一位同事使用typing Dict import typing def change bandwidths new bandwidths typing Dict user id int
  • 如何使用Python多处理创建同步对象?

    我无法弄清楚如何创建同步的 Python 对象 我有一个名为 Observation 的类和一个名为 Variable 的类 基本上看起来像这样 代码被简化以显示本质 class Observation def init self date
  • 如何将接口转换为接口切片?

    我的输入是interface 而且我知道它可以是任何类型的数组 我想读取我输入的元素之一 所以我尝试将我的interface 进入一个 interface 但是 go 会给我以下错误 恐慌 接口转换 interface 是 map stri

随机推荐