Golang-分段锁实现并发安全的Map

本文介绍了Golang中使用分段锁实现并发安全Map的原理和方法,包括New、Set/Get/Delete/Has等操作的实现。通过对比sync.Map,展示了分段锁在写多读少场景下性能优势,提供了项目源码链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Golang - 分段锁实现并发安全Map

一.引言

我们一般有两种方式来降低锁的竞争:

  • 第一种:减少锁的持有时间,sync.Map即是采用这种策略,通过冗余的数据结构,使得需要持有锁的时间,大大减少。
  • 第二种:降低锁的请求频率,锁分解和锁分段技术即是这种思想的体现。

锁分段技术又可称为分段锁机制

什么叫做分段锁机制?

将数据分为一段一段的存储,然后给每一段数据配备一把锁.

这样在多线程情况下,不同线程操作不同段的数据不会造成冲突,线程之间也不会存在锁竞争,有效的提高了并发访问的效率

二.实现原理

首先我们需要给数据进行分段,属于同一个段的数据放在一起,我们采用golang原生的map来充当段的容器,用于存储元素,将key通过哈希映射的形式分配到不同的段中。

// SharedMap 并发安全的小map,ShardCount 个这样的小map数组组成一个大map
type SharedMap struct {
	items        map[string]interface{}
	sync.RWMutex // 读写锁,保护items
}

可以看到,我们给每个段都配备了一个内置的读写锁,用于保护段内的数据安全

// ShardCount 底层小shareMap数量
var ShardCount = 32

// ConcurrentHashMap 并发安全的大map,由 ShardCount 个小mao数组组成,方便实现分段锁机制
type ConcurrentHashMap []*SharedMap

然后 ShardCount 个ShareMap就组成了一个大的并发安全的map。

其哈希函数采用了著名的fnv函数

// fnv32 hash函数
func fnv32(key string) uint32 {
   // 著名的fnv哈希函数,由 Glenn Fowler、Landon Curt Noll和 Kiem-Phong Vo 创建
   hash := uint32(2166136261)
   const prime32 = uint32(16777619)
   keyLength := len(key)
   for i := 0; i < keyLength; i++ {
      hash *= prime32
      hash ^= uint32(key[i])
   }
   return hash
}

1.New

// New 创建一个新的concurrent map.
func New() ConcurrentHashMap {
   m := make(ConcurrentHashMap, ShardCount)
   for i := 0; i < ShardCount; i++ {
      m[i] = &SharedMap{items: make(map[s
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值