如何从并发映射写入中恢复?

How to recover from concurrent map writes?

如何从 "concurrent map read and map write" 上的运行时恐慌中恢复?通常的 defer with recover 似乎不起作用。这是为什么?

我知道您不应该在并发上下文中使用映射,但仍然:如何在此处恢复?

示例:

package main

import "time"

var m = make(map[string]string)

func main() {
    go func() {
        for {
            m["x"] = "foo"
        }
    }()
    go func() {
        for {
            m["x"] = "foo"
        }
    }()

    time.Sleep(1 * time.Second)
}

请添加恢复代码。 :)

不要恢复,用互斥体形式包保护你的代码 sync

package main

import (
    "sync"
    "time"
)

var m = make(map[string]string)
var l = sync.Mutex{}

func main() {
    go func() {
        for {
            l.Lock()
            m["x"] = "foo"
            l.Unlock()
        }
    }()
    go func() {
        for {
            l.Lock()
            m["x"] = "foo"
            l.Unlock()
        }
    }()

    time.Sleep(1 * time.Second)
}

恢复在这里不起作用,因为您所经历的不是恐慌状态。

Go 1.6 added 对运行时的地图检测的轻量级并发滥用:

The runtime has added lightweight, best-effort detection of concurrent misuse of maps. As always, if one goroutine is writing to a map, no other goroutine should be reading or writing the map concurrently. If the runtime detects this condition, it prints a diagnosis and crashes the program. The best way to find out more about the problem is to run the program under the race detector, which will more reliably identify the race and give more detail.

您遇到的是运行时故意崩溃,这不是 panic() 调用的结果,而是 recover() 延迟函数中的调用可以停止。

除了防止同时滥用地图之外,您无能为力。如果你让你的应用程序保持这样并且它不会崩溃,你可能会在运行时遇到神秘的、未定义的行为。