为什么即使有锁,GO 也会因“并发映射写入”而恐慌?

当尝试将此结构与多个 goroutine 一起使用时,有时我会遇到以下错误之一:

fatal error: concurrent map read and map write

或者

concurrent map writes

阅读此线程后,我确保在构造函数中返回一个引用并将引用传递给接收者。

使用它的全部代码都在这个 github repo中

type concurrentStorage struct {

    sync.Mutex

    domain string

    urls map[url.URL]bool

}


func newConcurrentStorage(d string) *concurrentStorage{

    return &concurrentStorage{

        domain: d,

        urls: map[url.URL]bool{},

    }

}


func (c *concurrentStorage) add(u url.URL) (bool) {

    c.Lock()

    defer c.Unlock()

    if _, ok := c.urls[u]; ok{

        return false

    }

    c.urls[u] = true

    return true

}


12345678_0001
浏览 91回答 1
1回答

翻翻过去那场雪

在阅读您链接到的 Github 上的代码后,该crawl()函数接受一个concurrentStorage(不是指针)。*urlSet对于调用 时的每个取消引用(即:)crawl(),您正在复制concurrentStorage结构(包括sync.Mutex),而地图保留指向原始结构的指针。这意味着您的互斥体与每个 goroutine 是隔离的,同时它们共享相同的状态。如果您更改crawl()为接受指针,并停止取消引用concurrentStorage,它将按您的预期工作。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go