You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang中Mutex锁锁定对象解析及缓存锁区分与实现疑问

在Go语言中,Mutex锁到底锁定的是什么?

Go 中的sync.Mutex并不直接锁定任何对象或内存区域,它的核心作用是保证临界区代码的互斥执行——同一时间只能有一个 goroutine 进入被它包裹的代码块。

你可以把它理解成一个"准入令牌":拿到令牌的 goroutine 才能操作共享资源,没拿到的必须等待。它通过控制代码执行的排他性,间接避免共享数据被并发读写破坏。


针对代码区分globalLock与EntryLock,以及实现单key锁定

先看给出的结构体定义:

type cacheImpl struct {
    globalLock       sync.Mutex
    EntryLock map[string]*sync.Mutex
        
    abc map[string]int
}

二者的区别与锁定对象

  • globalLock:全局互斥锁,负责保护abc这个 map 的结构安全。比如对 map 执行添加/删除 key、初始化这类修改结构的操作,或者遍历整个 map 时,必须用它来保证并发安全。它锁定的是整个 map 结构,只要它被持有,所有涉及 map 结构变更的操作都得等待。
  • EntryLock:以 string 为 key 的锁集合,作用是为abc中单个 key 对应的 int 值提供细粒度锁定。不同 key 的操作可以并发执行,不用互相阻塞,比全局锁的性能更优。

如何创建EntryLock实现单key锁定

要实现每个 key 对应独立的锁,需要在首次操作该 key 时创建对应的 Mutex,且创建锁的过程要保证并发安全,通常结合 globalLock 来实现:

完整示例代码

1. 初始化 cache

func NewCache() *cacheImpl {
    return &cacheImpl{
        abc:       make(map[string]int),
        EntryLock: make(map[string]*sync.Mutex),
    }
}

2. 单key操作的示例方法

func (c *cacheImpl) GetOrSet(key string, val int) int {
    // 先获取全局锁,检查并创建对应key的锁,减少全局锁持有时间
    c.globalLock.Lock()
    lock, ok := c.EntryLock[key]
    if !ok {
        lock = &sync.Mutex{}
        c.EntryLock[key] = lock
    }
    c.globalLock.Unlock()

    // 持有单个key的锁,操作对应的value
    lock.Lock()
    defer lock.Unlock()

    if v, exists := c.abc[key]; exists {
        return v
    }
    c.abc[key] = val
    return val
}

3. 删除key时清理锁(避免内存泄漏)

func (c *cacheImpl) Delete(key string) {
    // 先从锁集合中移除对应key的锁
    c.globalLock.Lock()
    lock, ok := c.EntryLock[key]
    if ok {
        delete(c.EntryLock, key)
    }
    c.globalLock.Unlock()

    // 锁定对应key的锁,确保没有并发操作
    if lock != nil {
        lock.Lock()
        defer lock.Unlock()
    }

    // 最后删除map中的key
    c.globalLock.Lock()
    delete(c.abc, key)
    c.globalLock.Unlock()
}

内容的提问来源于stack exchange,提问作者SWATHI.M SHETTY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:44:59