为什么 GO 会因为 'concurrent map writes' 出现恐慌,即使有锁?
Why GO panics with 'concurrent map writes' even with locks in place?
当尝试将此结构与多个 goroutine 一起使用时,有时我会遇到以下错误之一:
fatal error: concurrent map read and map write
或
concurrent map writes
阅读 this thread 后,我确保 return 构造函数中的引用并将引用传递给接收者。
使用此代码的全部代码在 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
,它将按您的预期工作。
当尝试将此结构与多个 goroutine 一起使用时,有时我会遇到以下错误之一:
fatal error: concurrent map read and map write
或
concurrent map writes
阅读 this thread 后,我确保 return 构造函数中的引用并将引用传递给接收者。
使用此代码的全部代码在 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
,它将按您的预期工作。