go map的并发读写

xyzasd01 · 2017-08-21 14:13:14 · 5509 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2017-08-21 14:13:14 的主题,其中的信息可能已经有所发展或是发生改变。

我加了锁,可还是报错。 fatal error: concurrent map iteration and map write

这是为何呢?百度的各种方法也都试了,都不行。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var counter = struct{
        sync.RWMutex
        m map[string]int
    }{m: make(map[string]int)}
    for i := 0; i < 2; i++ {
        go func() {
            for j := 0; j < 1000000; j++ {
                counter.Lock()
                counter.m["some_key"]++
                counter.Unlock()
            }

        }()
    }
    fmt.Println(counter)
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

5509 次点击  
加入收藏 微博
8 回复  |  直到 2017-08-24 14:13:26
polaris
polaris · #1 · 8年之前

你只顾着写的时候加锁,读也得加。fmt.Println(counter) 你把它给忘了!

xiaopengxu
xiaopengxu · #2 · 8年之前

楼上正解,读的地方加个读锁RLock即可

marlonche
marlonche · #3 · 8年之前

所有崩溃都可以很容易在崩溃后打印的调用堆栈里面找到原因

fatal error: concurrent map iteration and map write

goroutine 7 [running]:
runtime.throw(0x4aae87, 0x26)
        /usr/local/go/src/runtime/panic.go:596 +0x95 fp=0xc42003a840 sp=0xc42003a820
runtime.mapiternext(0xc420086060)
        /usr/local/go/src/runtime/hashmap.go:737 +0x7ee fp=0xc42003a8f0 sp=0xc42003a840
reflect.mapiternext(0xc420086060)
        /usr/local/go/src/runtime/hashmap.go:1156 +0x2b fp=0xc42003a908 sp=0xc42003a8f0
reflect.Value.MapKeys(0x490200, 0xc42007a078, 0xb5, 0x0, 0x76, 0x2)
        /usr/local/go/src/reflect/value.go:1112 +0x1bc fp=0xc42003a9b8 sp=0xc42003a908
fmt.(*pp).printValue(0xc420082000, 0x490200, 0xc42007a078, 0xb5, 0x76, 0x1)
        /usr/local/go/src/fmt/print.go:741 +0xedf fp=0xc42003abb0 sp=0xc42003a9b8
fmt.(*pp).printValue(0xc420082000, 0x492c40, 0xc42007a060, 0x99, 0x76, 0x0)
        /usr/local/go/src/fmt/print.go:778 +0x21de fp=0xc42003ada8 sp=0xc42003abb0
fmt.(*pp).printArg(0xc420082000, 0x492c40, 0xc42007a060, 0x76)
        /usr/local/go/src/fmt/print.go:682 +0x217 fp=0xc42003ae30 sp=0xc42003ada8
fmt.(*pp).doPrintln(0xc420082000, 0xc42003af98, 0x1, 0x1)
        /usr/local/go/src/fmt/print.go:1138 +0xa1 fp=0xc42003aea8 sp=0xc42003ae30
fmt.Fprintln(0x4f7160, 0xc42000c018, 0xc42003af98, 0x1, 0x1, 0xc42007a060, 0xc42003afa8, 0xc42007a060)
        /usr/local/go/src/fmt/print.go:247 +0x5c fp=0xc42003af10 sp=0xc42003aea8
fmt.Println(0xc42003af98, 0x1, 0x1, 0xc42007a060, 0x0, 0x0)
        /usr/local/go/src/fmt/print.go:257 +0x57 fp=0xc42003af60 sp=0xc42003af10
main.main.func2(0xc42000a1a0)
        /home/marlon/projects/t.go:26 +0xb1 fp=0xc42003afd8 sp=0xc42003af60
runtime.goexit()
xyzasd01
xyzasd01 · #4 · 8年之前
polarispolaris #1 回复

你只顾着写的时候加锁,读也得加。`fmt.Println(counter)` 你把它给忘了!

谢谢~非常感谢。是我疏忽了。

xyzasd01
xyzasd01 · #5 · 8年之前
xiaopengxuxiaopengxu #2 回复

楼上正解,读的地方加个读锁`RLock`即可

非常感谢

631768417
631768417 · #6 · 8年之前

这不是一种好方式。。。在golang里也有类似java里面的 ConcurrentHashMap 。

自己加锁非常耗性能。功能上可以实现。一旦高并发,会发生阻塞点。。

给你推荐个极品方案

https://github.com/orcaman/concurrent-map

xyzasd01
xyzasd01 · #7 · 8年之前

@631768417 我正学到这里,就想试试为什么map不是并发安全的,最笨的就是加锁,所以试试,结果还报错了。谢谢您

xyzasd01
xyzasd01 · #8 · 8年之前

@631768417 我正学到这里,就想试试为什么map不是并发安全的,最笨的就是加锁,所以试试,结果还报错了。谢谢您

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传