英文:
How to setup key based Mutex (Lock and Unlock) in Golang?
问题
假设我有一组goroutine:
wg := sync.WaitGroup{}
wg.Add(5)
go somefunction("A", &wg) //1
go somefunction("B", &wg) //2
go somefunction("A", &wg) //3
go somefunction("A", &wg) //4
go somefunction("B", &wg) //5
wg.Wait()
我需要的是,只有一个特定字符串(这里是"A"或"B")的goroutine可以同时运行。在任何时候,只有一个somefunction("A", &wg)可以运行。例如,//1和//2开始同时运行。在//2完成后,//5开始运行。在//1完成后,//3或//4中的任何一个开始运行。
我考虑开发一个基于键的互斥锁来解决这个问题。
somefunction(key string){
Lock(key)
//一段代码
Unlock(key)
}
这段代码将会为特定的键进行锁定。
英文:
Suppose I have a set of goroutines
wg := sync.WaitGroup{}
wg.Add(5)
go somefunction("A", &wg) //1
go somefunction("B", &wg) //2
go somefunction("A", &wg) //3
go somefunction("A", &wg) //4
go somefunction("B", &wg) //5
wg.Wait()
What I require is that only one goroutine of a particular string ("A" or "B" here) run concurrently. At any time only one of somefunction("A", &wg) should run. For example, //1 and //2 starts running concurrently. After //2 is completed, //5 starts running. After //1 is completed, any one of //3 or //4 starts running.
I was thinking of developing a key based mutex to solve around this issue.
somefunction(key string){
Lock(key)
//piece of code
Unlock(key)
}
The piece of code will be locked for the particular key here.
答案1
得分: 1
让somefunction
接受一个互斥锁参数,并为相同的键传递相同的互斥锁实例。
func somefunction(mux *sync.Mutex, wg *sync.WaitGroup) {
mux.Lock()
defer mux.Unlock()
...
}
wg := &sync.WaitGroup{}
wg.Add(5)
muxA := &sync.Mutex{}
muxB := &sync.Mutex{}
go somefunction(muxA, wg) //1
go somefunction(muxB, wg) //2
go somefunction(muxA, wg) //3
go somefunction(muxA, wg) //4
go somefunction(muxB, wg) //5
wg.Wait()
如果你想继续使用基于键的访问,可以将互斥锁存储在一个映射中:
muxmap := map[string]*sync.Mutex{
"A": &sync.Mutex{},
"B": &sync.Mutex{},
}
go somefunction(muxmap["A"], wg)
英文:
Let somefunction
take a mutex param, and pass the same mutex instance for the same key.
func somefunction(mux *sync.Mutex, wg *sync.WaitGroup) {
mux.Lock()
defer mux.Unlock()
...
}
wg := &sync.WaitGroup{}
wg.Add(5)
muxA := &sync.Mutex{}
muxB := &sync.Mutex{}
go somefunction(muxA, wg) //1
go somefunction(muxB, wg) //2
go somefunction(muxA, wg) //3
go somefunction(muxA, wg) //4
go somefunction(muxB, wg) //5
wg.Wait()
If you want to keep using key-base access, you can store the mutexes in a map:
muxmap := map[string]*sync.Mutex{
"A": &sync.Mutex{},
"B": &sync.Mutex{},
}
go somefunction(muxmap["A"], wg)
答案2
得分: 1
可能可以实现一个特殊的锁,类似于:
type StringKeyLock struct {
locks map[string]*sync.Mutex
mapLock sync.Mutex // 用于在并发情况下保证 map 的安全性
}
func NewStringKeyLock() *StringKeyLock {
return &StringKeyLock{locks: make(map[string]*sync.Mutex)}
}
func (l *StringKeyLock) getLockBy(key string) *sync.Mutex {
l.mapLock.Lock()
defer l.mapLock.Unlock()
ret, found := l.locks[key]
if found {
return ret
}
ret = &sync.Mutex{}
l.locks[key] = ret
return ret
}
func (l *StringKeyLock) Lock(key string) {
l.getLockBy(key).Lock()
}
func (l *StringKeyLock) Unlock(key string) {
l.getLockBy(key).Unlock()
}
然后初始化一个"全局"的 StringKeyLock:
var stringKeyLock = NewStringKeyLock()
最后,使用它:
func somefunction(key string){
stringKeyLock.Lock(key)
// 一段代码
stringKeyLock.Unlock(key)
}
英文:
Probably can implement a special lock like
type StringKeyLock struct {
locks map[string]*sync.Mutex
mapLock sync.Mutex // to make the map safe concurrently
}
func NewStringKeyLock() *StringKeyLock {
return &StringKeyLock{locks: make(map[string]*sync.Mutex)}
}
func (l *StringKeyLock) getLockBy(key string) *sync.Mutex {
l.mapLock.Lock()
defer l.mapLock.Unlock()
ret, found := l.locks[key]
if found {
return ret
}
ret = &sync.Mutex{}
l.locks[key] = ret
return ret
}
func (l *StringKeyLock) Lock(key string) {
l.getLockBy(key).Lock()
}
func (l *StringKeyLock) Unlock(key string) {
l.getLockBy(key).Unlock()
}
Then to initialize a "global" StringKeyLock
var stringKeyLock = NewStringKeyLock()
Last, to use it
func somefunction(key string){
stringKeyLock.Lock(key)
//piece of code
stringKeyLock.Unlock(key)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论