goroutine 数据竞争的问题

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

func main() {
    // listen to incoming udp packets
    udpServer, err := net.ListenPacket("udp", ":1053")
    if err != nil {
        log.Fatal(err)
    }
    defer udpServer.Close()

    buf := make([]byte, 1024)

    for {
        //buf := make([]byte, 1024)
        n, addr, err := udpServer.ReadFrom(buf)
        if err != nil {
            continue
        }
        tmp := buf[:n]
        fmt.Println("tmp====", len(tmp), cap(tmp), hex.EncodeToString(tmp))
        go response(udpServer, addr, tmp)
    }

}

func response(udpServer net.PacketConn, addr net.Addr, buf []byte) {

    fmt.Println(len(buf), string(buf), hex.EncodeToString(buf))

    time := time.Now().Format(time.ANSIC)
    responseStr := fmt.Sprintf("time received: %v. Your message: %v!", time, string(buf))

    udpServer.WriteTo([]byte(responseStr), addr)
}

一个 udp 的客户端发送 "hello" 到这个 udp的服务器,同时期望会正确的显示 hello. 但是由于 response 会被操作系统在不可预知的情况下调度,或者说这个 hello 对应的 response 执行了 len(buf)后被操作系统挂起 另一个 udp 的客户端发送 "world" 到这个 udp的服务器,此时前面的那个 response 被操作系统重新调度,此时会打印出 "world",而不是预期的 "hello" ,不知道我判断对不对 多调多谢


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

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

3925 次点击  
加入收藏 微博
3 回复  |  直到 2023-05-25 12:33:51
hcnyf
hcnyf · #1 · 2年之前

我在本地使用特定字符串休眠的方法测试了一下,确实是像你说的那样的,我也是新手,如果有错请大佬们指正 gotest.png

wang229819838
wang229819838 · #2 · 2年之前

这样写就没有问题了 tmp := make([]byte, n) copy(tmp, buf[:n]) go response(udpServer, addr, tmp) 你也可以参数其他办法,避免多groutine 数据竞争就行了。

gorilla-go
gorilla-go · #3 · 2年之前

很简单, 因为切片是引用类型

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