教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 golang 并发访问map遇到的问题

golang 并发访问map遇到的问题

发布时间:2021-04-25   编辑:jiaochengji.com
教程集为您提供golang 并发访问map遇到的问题等资源,欢迎您收藏本站,我们将为您提供最新的golang 并发访问map遇到的问题资源

go提供了一种叫map的数据结构,可以翻译成映射,对应于其他语言的字典、哈希表。借助map,可以定义一个键和值,然后可以从map中获取、设置和删除这个值,尤其适合数据查找的场景。但是map的使用有一定的限制,如果是在单个协程中读写map,那么不会存在什么问题,如果是多个协程并发访问一个map,有可能会导致程序退出,并打印下面错误信息:

fatal error: concurrent map read and map write

上面的这个错误不是每次都会遇到的,如果并发访问的协程数不大,遇到的可能性就更小了。例如下面的程序:

package main

func main() {
    Map := make(map[int]int)

    for i := 0; i < 10; i   {
        go writeMap(Map, i, i)
        go readMap(Map, i)
    }

}

func readMap(Map map[int]int, key int) int {
    return Map[key]
}

func writeMap(Map map[int]int, key int, value int) {
    Map[key] = value
}

只循环了10次,产生了20个协程并发访问map,程序基本不会出错,但是如果将循环次数变大,比如10万,运行下面程序基本每次都会出错:

package main

func main() {
    Map := make(map[int]int)

    for i := 0; i < 100000; i   {
        go writeMap(Map, i, i)
        go readMap(Map, i)
    }

}

func readMap(Map map[int]int, key int) int {
    return Map[key]
}

func writeMap(Map map[int]int, key int, value int) {
    Map[key] = value
}

 

大致意思就是说,并发访问map是不安全的,会出现未定义行为,导致程序退出。所以如果希望在多协程中并发访问map,必须提供某种同步机制,一般情况下通过读写锁sync.RWMutex实现对map的并发访问控制,将map和sync.RWMutex封装一下,可以实现对map的安全并发访问,示例代码如下:

package main

import "sync"

type SafeMap struct {
    sync.RWMutex
    Map map[int]int
}

func main() {
    safeMap := newSafeMap(10)

    for i := 0; i < 100000; i   {
        go safeMap.writeMap(i, i)
        go safeMap.readMap(i)
    }

}

func newSafeMap(size int) *SafeMap {
    sm := new(SafeMap)
    sm.Map = make(map[int]int)
    return sm

}

func (sm *SafeMap) readMap(key int) int {
    sm.RLock()
    value := sm.Map[key]
    sm.RUnlock()
    return value
}

func (sm *SafeMap) writeMap(key int, value int) {
    sm.Lock()
    sm.Map[key] = value
    sm.Unlock()
}

但是通过读写锁控制map的并发访问时,会导致一定的性能问题,不过能保证程序的安全运行,牺牲点性能问题是可以的


转载链接:https://www.jianshu.com/p/10a998089486

到此这篇关于“golang 并发访问map遇到的问题”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
golang 并发访问map遇到的问题
一道并发和锁的golang面试题
go语言坑之并发访问map
golang:map
请教一个interface格式解析的问题
Golang 中使用 Slice 索引 Map 替代 Map 获得性能提升
Golang 中使用多维 map
Golang线程安全Map:sync.Map使用小结
Golang的map并发安全
golang map并发读写问题踩坑记录 `concurrent map read and map write`

[关闭]
~ ~