使用多个goroutine写入互斥体映射是否快于一个互斥体映射?为什么呢?

时间:2019-03-28 03:31:18

标签: go go-map

我的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时,有什么方法可以提高效率?

谢谢〜

1 个答案:

答案 0 :(得分:2)

这很简单。在第二种情况下,由于具有互斥锁,因此使用2个goroutine,一次只能有一个goroutine写入映射。因此,与仅使用一个goroutine依次进行操作并没有太大区别。在任何给定时间,只有一个goroutine会做任何事情。计数器和循环根本不占用太多时间,因此它们基本上可以忽略,这是映射写入花费的大部分时间。

但是,您还要支付锁争用的额外费用以及10,000次锁定和解锁操作,这是相当昂贵的。因此,这意味着整体速度会变慢。

总而言之,如果在任何给定时间仅运行一个goroutine,那么使用更多goroutine不会加快速度。

为了获得更高的效率,请使用更好的地图,例如thisthis。您创建的地图完全不允许并发。