go - 为什么即使有锁,GO 也会出现 'concurrent map writes' panic ?

标签 go concurrency mutex goroutine

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

fatal error :并发映射读取和映射写入

并发映射写入

看完this thread我确保在构造函数中返回一个引用,并将一个引用传递给接收者。

使用它的完整代码在 this 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
}

最佳答案

在阅读您链接到的 Github 上的代码后,crawl() 函数接受一个 concurrentStorage(不是指针)。

对于调用 crawl() 时的每个取消引用(即:*urlSet),您都在复制 concurrentStorage 结构(包括sync.Mutex) 而映射保留指向原始指针的指针。这意味着您的互斥量与每个 goroutine 是隔离的,同时它们共享相同的状态。

如果您将 crawl() 改为接受指针,并停止取消引用 concurrentStorage,它将按您的预期工作。

关于go - 为什么即使有锁,GO 也会出现 'concurrent map writes' panic ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52797446/

相关文章:

java - Kryo:IdentityObjectIntMap.clear() 产生巨大的 CPU 负载

c - pthread 互斥体无法正常工作

go - 一些如何在 go 程序使用中显示各种测试参数标志

asynchronous - 如何在 Rust 中竞赛 future 集合?

java - 用于在线程中发出信号的信号量不起作用(并发问题)

c - Pthreads - 我可以从线程分离然后加入主线程吗?

multithreading - 互斥锁 : what does "blocking" mean?

go - 如何使用gocql查询cassandra UDT?

web - Go 中的交互式网页

json - 我应该如何处理源代码中的大块文本,以免影响代码的可读性?