首页 > 解决方案 > 如何使用互斥锁有效地读写地图?

问题描述

我正在读取一个包含 1kk+ 个对象的 json 文件,我需要组织和计算一些数据,为此我创建了两个地图,这样当我运行一个简单的循环代码时,我就可以写入和读取它需要 40 秒才能完成,例如:

var acc int
firstContent := make(map[string]int)
secondContent := make(map[string]int)

decoder := json.NewDecoder(bufio.NewReader(file))

for decoder.More() {
    var dt &MyStruct{}
    decoder.Decode()

    if _, ok := firstContent[dt.Name]; !ok {
        firstContent["some-data"] = 1
        acc++ // count the uniqueness
    } else {
        firstContent["some-data"] += 1
    }

    if _, ok := secondContent[dt.City]; !ok {
        first["some-data"] = 1
    } else {
        first["some-data"] += 1
    }
}

我试图优化使用goroutinesmutex避免并发,但是当我使用它时,它需要更长的时间才能完成。

var mutex = sync.RWMutex{}

for reader.More() {
    var dt &MyStruct{}
    reader.Decode(&dt)

    go func(name string) {
        mutex.Lock()
        if _, ok := firstContent[name]; !ok {
            firstContent[name] = 1 // need to convert to *int64, i know...
            atomic.AddInt32(acc, 1)
        } else {
            atomic.AddInt64(firstContent[name], 1)
        }
        mutex.Unlock()
    }(dt.Name)

    go func(city string) {
        mutex.Lock()
        if _, ok := secondContent[city]; !ok {
            secondContent[city] = 1
        } else {
            atomic.AddInt(secondContent[city], 1)
        }
        mutex.Unlock()
    }(dt.City)
}

为什么需要更长的时间才能完成?因为mutex.Lock()?在这种情况下如何提高速度?

标签: go

解决方案


就像上面的 Jakub 所说,您可以将输入文件和进程拆分到单独的 goroutine(如 MapReduce 框架)上,这肯定会加快速度。

另外,您是否尝试过在 JSON 文件中创建对象的 go-struct 并将其编组到它们的列表中并从那里进行计算?不确定这是否会更好,但这是一个想法。


推荐阅读