草庐IT

dictionary - Golang fatal error : concurrent map read and map write

coder 2023-06-25 原文

我正在用 Go 编写 minecraft 服务器,当服务器受到 2000 多个连接的压力时,我遇到了这个崩溃:

fatal error: concurrent map read and map write/root/work/src/github.com/user/imoobler/limbo.go:78 +0x351 created by main.main /root/work/src/github.com/user/imoobler/limbo.go:33 +0x368

我的代码:

package main

import (
    "log"
    "net"
    "bufio"
    "time"
    "math/rand"
    "fmt"
)

var (
    connCounter = 0
)

func main() {
    InitConfig()
    InitPackets()

    port := int(config["port"].(float64))
    ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
    if err != nil {
        log.Fatal(err)
    }
    log.Println("Server launched on port", port)
    go KeepAlive()
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Print(err)
        } else {
            connCounter+=1
            go HandleConnection(conn, connCounter)
        }
    }
}

func KeepAlive() {
    r := rand.New(rand.NewSource(15768735131534))
    keepalive := &PacketPlayKeepAlive{
        id: 0,
    }
    for {
        for _, player := range players {
            if player.state == PLAY {
                id := int(r.Uint32())
                keepalive.id = id
                player.keepalive = id
                player.WritePacket(keepalive)
            }
        }
        time.Sleep(20000000000)
    }
}

func HandleConnection(conn net.Conn, id int) {
    log.Printf("%s connected.", conn.RemoteAddr().String())

    player := &Player {
        id: id,
        conn: conn,
        state: HANDSHAKING,
        protocol: V1_10,
        io: &ConnReadWrite{
            rdr: bufio.NewReader(conn),
            wtr: bufio.NewWriter(conn),
        },
        inaddr: InAddr{
            "",
            0,
        },
        name: "",
        uuid: "d979912c-bb24-4f23-a6ac-c32985a1e5d3",
        keepalive: 0,
    }

    for {
        packet, err := player.ReadPacket()
        if err != nil {
            break
        }

        CallEvent("packetReceived", packet)
    }

    player.unregister()
    conn.Close()
    log.Printf("%s disconnected.", conn.RemoteAddr().String())
}

目前服务器只是“悬而未决”。

最佳答案

一般来说(无法访问发生错误的代码)您有几种选择。这是其中两个:

同步.RWMutex

使用 sync.RWMutex{} 控制对 map 的访问。如果您有单次读取和写入,而不是在 map 上循环,请使用此选项。参见 RWMutex

这里是一个示例,通过 someMapMutexsomeMap 进行了访问控制:

var (
    someMap      = map[string]string{}
    someMapMutex = sync.RWMutex{}
)

go func() {
    someMapMutex.Lock()
    someMap["key"] = "value"
    someMapMutex.Unlock()
}()

someMapMutex.RLock()
v, ok := someMap["key"]
someMapMutex.RUnlock()
if !ok {
    fmt.Println("key missing")
    return
}
fmt.Println(v)

syncmap.Map

使用 syncmap.Map{} 而不是普通的 map。该 map 已经在处理种族问题,但根据您的使用情况可能会更慢。 syncmap.Map{} 的主要优势在于 for 循环。参见 syncmap

var (
    someMap = syncmap.Map{}
)

go func() {
    someMap.Store("key", "value")
}()

v, ok := someMap.Load("key")
if !ok {
    fmt.Println("key missing")
    return
}
fmt.Println(v)

// with syncmap, looping over all keys is simple without locking the whole map for the entire loop
someMap.Range(func(key, value interface{}) bool {
    // cast value to correct format
    val, ok := value.(string)
    if !ok {
        // this will break iteration
        return false
    }
    // do something with key/value
    fmt.Println(key, val)

    // this will continue iterating
    return true
})

一般建议

您应该使用 -race 选项测试您的服务器,然后消除它抛出的所有竞争条件。这样您就可以更轻松地在此类错误发生之前将其消除。

go run -race server.go

参见 golang race detector

关于dictionary - Golang fatal error : concurrent map read and map write,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45585589/

有关dictionary - Golang fatal error : concurrent map read and map write的更多相关文章

  1. ruby - 在 OSX 上以编程方式使用 Dictionary.app 的词库功能(最好通过 Ruby) - 2

    我需要编写一个Ruby方法,它接受一个词,通过OS10.5的Dictionary.app的同义词库函数运行它,并返回备选词。如果Ruby方法最终调用命令行,那很好;我只需要能够从Ruby以编程方式完成它。查看RubyOSA后,我意识到可以通过某些词典服务访问词典[http://discussions.apple.com/thread.jspa?threadID=1561332],但我真的不明白。有人看到一个简单的解决方案吗?我也准备制作一个Automator工作流程并从命令行调用它,但由于某种原因我无法从shell中正确地为“获取定义”函数提供一个词(它一直说它不能'找到这个词,但是当

  2. javascript相当于python的dictionary.get - 2

    我正在尝试使用node.js验证JSON对象。基本上,如果存在条件A,那么我想确保某个特定值位于可能不存在的数组中。我在python中使用dictionary.get执行此操作,因为如果我查找不存在的内容,它将返回默认值。这是它在python中的样子ifoutput.get('conditionA')andnot'conditionB'inoutput.get('deeply',{}).get('nested',{}).get('array',[]):print"Thereisanerrorsomewhereyouneedtobefixing."我想为javascript找到类似的技术

  3. c# - 使用 JSON.net 序列化 Dictionary<int,object>? - 2

    我正在尝试使用JSON.net来序列化字典。使用JsonConvert.SerializeObject(theDict);这是我的结果{"1":{"Blah1":false,"Blah2":false,"Blah3":"None","Blah4":false},"2":{"Blah1":false,"Blah2":false,"Blah3":"None","Blah4":false},"3":{"Blah1":false,"Blah2":false,"Blah3":"None","Blah4":false},.........}有没有办法序列化这个字典,以便将键呈现为有效的javasc

  4. 已解决ValueError: dictionary update sequence element #0 has length 1; 2 is required - 2

    已解决ValueError:dictionaryupdatesequenceelement#0haslength1;2isrequired文章目录报错问题报错翻译报错内容解决方法千人全栈VIP答疑群联系博主帮忙解决报错报错问题粉丝群里面的一个小伙伴,想用Python爬虫然后解析数据,但是发生了报错(当时他心里瞬间凉了一大截,跑来找我求助,然后顺利帮助他解决了,顺便记录一下希望可以帮助到更多遇到这个bug不会解决的小伙伴),报错代码如下所示:defspider(page=1):""":parampage::return:"""url="http://www.ceic.ac.cn/ajax/sea

  5. dictionary - 如何将 map 转换为条目 slice ? - 2

    我正在尝试将键值映射转换为成对slice,例如给定如下映射:m:=make(map[int64]int64)m[521]=4m[528]=8我如何将其转换成其条目的一部分,例如:[[521,4],[528,8]]我正在考虑遍历所有这些键值然后为其创建slice,但是是否有任何简单的代码可以做到这一点? 最佳答案 packagemainimport"fmt"funcmain(){//createamapm:=map[int64]int64{512:8,513:9,234:9,392:0}//createaslicetoholdrequ

  6. dictionary - 如何将具有嵌套对象的复杂 json 字符串转换为在 golang 中映射? - 2

    我有一个复杂的json格式字符串,我想将其转换为golang中的map。假设字符串是species:{"type":"human""age":"23""attributes":{"height":"182""weight":"160""contact":{"address":########"phone":#########}}}我如何解析它使得map[attributes]又是一个map[string]接口(interface)等等? 最佳答案 您可以使用map[string]interface{},例如:species:=mak

  7. dictionary - 从 map[string]string 获取单个键值 - 2

    我的cookie中存储了一张map,如下所示:cookieData:=map[expiration:1533455712ip:[hash:dd363d13234566727743277e96email:user@user.com]fmt.Println(reflect.TypeOf(cookie))>>map[string]string有人可以帮助我了解如何从这张map中只获取电子邮件值吗?提前致谢。 最佳答案 golang中的类型转换是通过附加.(T)完成的ip:=cookieData["ip"].(map[string]stri

  8. dictionary - 如何从使用接口(interface){}键入的 golang map[string] 字符串中提取值 - 2

    这个问题在这里已经有了答案:ExplainTypeAssertionsinGo(3个答案)AccessingNestedMapofTypemap[string]interface{}inGolang(2个答案)Typed,nestedmapofmap[string]interface{}returns"typeinterface{}doesnotsupportindexing"(1个回答)getvalueformnestedmaptypemap[string]interface{}(2个答案)howtoaccessnestedJsonkeyvaluesinGolang(3个答案)关闭3

  9. dictionary - 如何在 golang 中遍历嵌套结构? - 2

    我是Golang的新手:这些是我定义的结构:typeNamemap[string]InfotypeInfostruct{Addressesstring`json:"addresses"`Hostmap[string]Server`json:"host"`}typeServerstruct{Ipaddressstring`json:"ip"`Statusstring`json:"status"`}varresultName解码Json后我得到:result=[user1:{192.168.98.0/26map[xx.user1.domain.com:{192.168.98.1good}x

  10. dictionary - 在 map 中存储值和 slice - 2

    如何在map中存储既可以是Type又可以是[]Type的值?我试过这个:mymap:=make(map[string]interface{})mymap["string"]="word"mymap["vector"]=append(mymap["vector"].([]interface{}),"earth")但是我有一个错误:panic:interfaceconversion:interface{}isnil,not[]interface{}这样的mymap的目的是将它用于json.Marshal以获取json对象,如下所示:{"string":"word","vector":["e

随机推荐