go - 如何在无错误的情况下按键编写互斥锁?

标签 go mutex

我想写一个像https://github.com/im7mortal/kmutex一样的互斥锁。 ,但思路不同。只是将互斥锁存储在hashmap中。但我的代码中总是存在一些死锁。我如何找到错误?还是有更好的方法来编写 key 互斥体?

package kmutex

import (
    "sync"
)

type keyMutex struct {
    localLockMap map[string]*sync.Mutex
    globalLock   sync.Mutex
}

func NewKeyMutex() *keyMutex {
    return &keyMutex{localLockMap: map[string]*sync.Mutex{}}
}

func (km *keyMutex) Lock(key string) {
    km.globalLock.Lock()

    wl, ok := km.localLockMap[key]

    if !ok {
        wl = &sync.Mutex{}
        km.localLockMap[key] = wl
    }

    km.globalLock.Unlock()

    wl.Lock()
}

func (km *keyMutex) Unlock(key string) {
    km.globalLock.Lock()

    wl, ok := km.localLockMap[key]

    if !ok {
        km.globalLock.Unlock()
        return
    }

    delete(km.localLockMap, key)

    km.globalLock.Unlock()

    wl.Unlock()
}

下面是测试代码

func TestKeyMutex1(t *testing.T) {

    keyMutex := kmutex.NewKeyMutex()

    //var keyMutex sync.Mutex

    var count = 0

    var wg sync.WaitGroup

    var num = 100

    for i := 1; i <= num; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            keyMutex.Lock("a")
            count += i
            keyMutex.Unlock("a")
        }(i)
    }

    wg.Wait()

    println(count)

}

它总是有死锁。在我删除行 delete(km.localLockMap, key) 之后。死锁消失了!但是还是看不懂

最佳答案

问题确实是删除映射中的互斥量。

考虑在同一个条目(“a”)中按以下顺序运行三个锁(当然是在多个 goroutine 中):

keyMutex.Lock("a") // lock1
keyMutex.Lock("a") // lock2
keyMutex.Lock("a") // lock3
keyMutex.Unlock("a") // unlock1
keyMutex.Unlock("a") // unlock2
keyMutex.Unlock("a") // unlock3

lock1在map中创建一个mutex,然后lock2lock3获取相同的mutex,阻塞在mutex的Lock上。 unlock1 找到互斥量,将其解锁并将其从映射中移除,解锁 lock2(或 lock3,但为了讨论起见,假设它是锁2)。但是当 unlock2unlock3 运行时,它在映射中发现没有互斥体,没有解锁任何东西,并保持 lock3 阻塞,因此出现死锁。

从映射中删除互斥量的行根本没有意义:互斥量是可重用的,在上下文中,只有对相同的条目使用相同的互斥量才是明智的。

关于go - 如何在无错误的情况下按键编写互斥锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55988340/

相关文章:

arrays - 使用字节 slice (或数组)时优化 go (golang) 代码的一些技巧是什么?

python - 为什么 Python 的 multiprocessing.Queue 不阻塞

c++ - condition_variable 获取锁速度慢

C,尽管有互斥锁,但在循环中初始化的 pthreads 没有正确执行分配的函数

c++ - 有意互斥传递的 pthread

templates - golang 模板中的调用链

regex - 使用 Golang 中的正则表达式确保特定字符在字符串中,无论位置如何

go - 遍历已解析的CSV时出错,出现紧急情况:运行时错误:索引超出范围[0],长度为0

c++ - boost mutex, condition, scoped_lock ,我在这里用错了吗?

c++ - 在 C++11 中实现线程安全方法的正确方法