面试题答案
一键面试1. 读写锁竞争问题
- 普通map加锁:普通map在高并发读写场景下,通常使用
sync.Mutex
或sync.RWMutex
进行保护。当多个读操作同时进行时,读锁竞争相对较小,但一旦有写操作,就需要独占锁,这会导致其他读、写操作都被阻塞。在高并发场景下,频繁的锁竞争会大大降低性能。 - sync.Map:sync.Map内部采用了更细粒度的锁机制。它将数据分散存储在多个
read
和dirty
结构中。读操作优先从read
中获取数据,read
结构是无锁的,只有在read
中找不到数据时才会尝试获取锁从dirty
中读取,这大大减少了读操作的锁竞争。写操作时,sync.Map会先尝试更新read
中的数据,如果read
中不存在则更新dirty
,这种方式减少了写操作对读操作的影响。
2. 动态扩容与缩容
- 普通map加锁:普通map本身没有动态扩容和缩容的能力,开发者需要手动管理其容量。在高并发场景下,手动扩容和缩容操作需要加锁保证数据一致性,这会增加锁的持有时间,降低并发性能。
- sync.Map:sync.Map内部实现了动态扩容和缩容机制,并且这些操作对用户透明。在高并发场景下,sync.Map能根据负载自动调整内部数据结构,减少因扩容或缩容带来的性能损耗,同时由于其更细粒度的锁机制,扩容和缩容操作对整体并发性能的影响也相对较小。
3. 键值对删除操作
- 普通map加锁:普通map删除键值对时需要加锁,这会阻塞其他读、写操作。在高并发场景下,如果频繁进行删除操作,锁竞争会加剧,影响系统性能。
- sync.Map:sync.Map删除键值对时,会先在
read
中标记为已删除,只有当dirty
提升为read
时,才真正删除数据。这种延迟删除的策略减少了删除操作对读操作的影响,并且在高并发场景下,由于减少了锁的使用频率,性能优势明显。
4. 数据清理与GC
- 普通map加锁:普通map在删除键值对后,相关内存不会立即释放,需要等待垃圾回收(GC)。在高并发场景下,大量的删除操作可能导致内存长时间无法释放,影响系统性能。
- sync.Map:sync.Map的延迟删除策略使得垃圾回收更高效。当
dirty
提升为read
时,会清理已标记为删除的数据,这有助于及时释放内存,减少GC压力,从而在高并发场景下提升系统整体性能。