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

时间:2016-09-02 09:17:02

标签: dictionary go concurrency goroutine panic

如何从“并发地图读取和地图写入”的运行时恐慌中恢复?恢复的通常延迟似乎不起作用。那是为什么?

我知道你不应该在并发环境中使用地图,但仍然:如何在这里恢复?

示例:

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)
}

请添加恢复代码。 :)

2 个答案:

答案 0 :(得分:14)

恢复在这里不起作用,因为你所经历的并不是一个惊慌失措的状态。

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

  

运行时添加了轻量级,尽力而为的并发滥用映射的方法。和往常一样,如果一个goroutine正在写一张地图,那么其他任何goroutine都不应该同时读取或写入地图。 如果运行时检测到这种情况,它会打印诊断并使程序崩溃。了解问题的最佳方法是在race detector下运行程序,这将更加可靠确定比赛并提供更多细节。

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

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

答案 1 :(得分:1)

请勿使用互斥锁格式包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)
}