当尝试将此结构与多个goroutine一起使用时,有时会出现以下错误之一:
fatal error: concurrent map read and map write
或
concurrent map writes
在阅读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
}
答案 0 :(得分:4)
在读取链接到的Github上的代码后,crawl()
函数将接受concurrentStorage
(不是指针)。
对于调用*urlSet
时的每个取消引用(即crawl()
),您正在复制concurrentStorage
结构(包括sync.Mutex
),而映射保留了指针到原来的。这意味着您的互斥锁在每个goroutine共享相同的状态时被隔离。
如果您将crawl()
改为接受指针,然后停止取消对concurrentStorage
的引用,它将按预期工作。