用于同步实体行为的有界"互斥池"



我有一个函数

type Command struct {
id Uuid
}
handleCommand(cmd Command) 
{
entity := lookupEntityInDataBase(cmd.Uuid)
entity.handleCommand(cmd)
saveEntityInDatabase(entity)
}

然而,这个函数可以并行调用,并且假设实体是非线程安全的,这会导致实体状态和将保存在数据库中的状态的racyness。

在该函数的开头和结尾进行简单的互斥锁可以解决这个问题,但会导致过于悲观的同步,因为应该允许不同实例(即不同uuid(的实体并行处理它们的命令。

另一种选择是保留map[uuid]sync.Mutex的Map,如果以前没有遇到uuid,则创建一个新的互斥体,并以线程安全的方式创建它。然而,这将导致运行时遇到的所有uuid的映射可能会无限增长。

我想过之后清理互斥体,但这样做是线程安全的,并意识到另一个线程可能已经在等待互斥体打开了很多蠕虫。

我希望我错过了一个非常简单和优雅的解决方案。

没有真正优雅的解决方案。以下是使用通道的版本:

var m map[string]chan struct{}
var l sync.Mutex
func handleCommand(cmd Command) {
for {
l.Lock()
ch, ok:=m[cmd.Uuid]
if !ok {
ch=make(chan struct{})
m[uuid]=ch
defer func() {
l.Lock()
delete(m,cmd.Uuid)
close(ch)
l.Unlock()
}()
l.Unlock()
break
}
l.Unlock()
<-ch
}
entity := lookupEntityInDataBase(cmd.Uuid)
entity.handleCommand(cmd)
saveEntityInDatabase(entity)
}

Moby项目有一个库,请参阅https://github.com/moby/locker

一行的描述是,

locker提供了一种创建细粒度锁定的机制,以帮助释放更多全局锁来处理其他任务

最新更新