写入具有多个 goroutine 的互斥映射是否比一个更快?为什么?
Is writing to a mutex map with multiple goroutines faster than one? and why?
我有一个 SyncMap 定义如下:
type SyncMap struct {
sync.Mutex
Map map[int]string
}
而且,现在我使用两种方式写入它,一种是 goroutine,另一种是带互斥锁的 goroutine。代码如下:
smap := SyncMap{}
smap.Map = make(map[int]string)
t1 := time.Now()
for i := 0; i < 10000; i++ {
smap.Map[i] = strconv.Itoa(i)
}
elapsed := time.Since(t1)
fmt.Println("t1 elapsed", elapsed)
s2map := SyncMap{}
s2map.Map = make(map[int]string)
t2 := time.Now()
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 5000; i++ {
s2map.Lock()
s2map.Map[i] = strconv.Itoa(i)
s2map.Unlock()
}
}()
go func() {
defer wg.Done()
for i := 5000; i < 10000; i++ {
s2map.Lock()
s2map.Map[i] = strconv.Itoa(i)
s2map.Unlock()
}
}()
wg.Wait()
elapsed2 := time.Since(t2)
fmt.Println("t2 elapsed", elapsed2)
输出如下:
t1 elapsed 5.0363ms
t2 elapsed 5.9353ms
试试服务时间,t1总是比t2快。
所以,我的问题正如标题所说。
我能理解这是因为互斥锁的消耗吗?这种情况下的 SyncMap 或 go 包中的 sync.Map 只是为了安全地编写 goroutine 而设计的,而不是为了效率?在用多个 goroutine 编写 map 时,有什么方法可以提高效率吗?
谢谢~
这很简单。在第二种情况下,对于 2 个 goroutine,由于互斥锁,一次只能有一个 goroutine 写入映射。因此,这与仅使用一个 goroutine 顺序执行它并没有太大区别。在任何给定时间,只有一个 goroutine 会做任何事情。计数器和循环根本不会消耗太多时间,因此基本上可以忽略它们,大部分时间是映射写入。
但是,您还有锁争用的额外成本,以及 10,000 次锁定和解锁操作,这些成本相当高。所以这意味着总体上它会更慢。
总而言之,如果在任何给定时间只有一个 goroutine 运行,则使用更多 goroutine 不会加快速度。
我有一个 SyncMap 定义如下:
type SyncMap struct {
sync.Mutex
Map map[int]string
}
而且,现在我使用两种方式写入它,一种是 goroutine,另一种是带互斥锁的 goroutine。代码如下:
smap := SyncMap{}
smap.Map = make(map[int]string)
t1 := time.Now()
for i := 0; i < 10000; i++ {
smap.Map[i] = strconv.Itoa(i)
}
elapsed := time.Since(t1)
fmt.Println("t1 elapsed", elapsed)
s2map := SyncMap{}
s2map.Map = make(map[int]string)
t2 := time.Now()
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 5000; i++ {
s2map.Lock()
s2map.Map[i] = strconv.Itoa(i)
s2map.Unlock()
}
}()
go func() {
defer wg.Done()
for i := 5000; i < 10000; i++ {
s2map.Lock()
s2map.Map[i] = strconv.Itoa(i)
s2map.Unlock()
}
}()
wg.Wait()
elapsed2 := time.Since(t2)
fmt.Println("t2 elapsed", elapsed2)
输出如下:
t1 elapsed 5.0363ms
t2 elapsed 5.9353ms
试试服务时间,t1总是比t2快。 所以,我的问题正如标题所说。
我能理解这是因为互斥锁的消耗吗?这种情况下的 SyncMap 或 go 包中的 sync.Map 只是为了安全地编写 goroutine 而设计的,而不是为了效率?在用多个 goroutine 编写 map 时,有什么方法可以提高效率吗?
谢谢~
这很简单。在第二种情况下,对于 2 个 goroutine,由于互斥锁,一次只能有一个 goroutine 写入映射。因此,这与仅使用一个 goroutine 顺序执行它并没有太大区别。在任何给定时间,只有一个 goroutine 会做任何事情。计数器和循环根本不会消耗太多时间,因此基本上可以忽略它们,大部分时间是映射写入。
但是,您还有锁争用的额外成本,以及 10,000 次锁定和解锁操作,这些成本相当高。所以这意味着总体上它会更慢。
总而言之,如果在任何给定时间只有一个 goroutine 运行,则使用更多 goroutine 不会加快速度。