为了账号安全,请及时绑定邮箱和手机立即绑定

GO里面MAP如何实现key不存在 get操作等待 直到key存在或者超时,保证并发安全

GO里面MAP如何实现key不存在 get操作等待 直到key存在或者超时,保证并发安全

jeck猫 2019-04-27 22:16:31
保证并发安全,实现如下接口typespinterface{Out(keystring,valinterface{})//存入key/val,如果该key读取的goroutine挂起,则唤醒。此方法不会阻塞,时刻都可以立即执行并返回Rd(keystring,timeouttime.Duration)interface{}//读取一个key,如果key不存在阻塞,等待key存在或者超时}
查看完整描述

2 回答

?
九州编程

TA贡献1785条经验 获得超4个赞

可以利用channel关闭goroutine不阻塞特性来实现:
下面的代码可以实现你的需求,只是没有写key被多次写入的判断逻辑。
typespinterface{
Out(keystring,valinterface{})//存入key/val,如果该key读取的goroutine挂起,则唤醒。此方法不会阻塞,时刻都可以立即执行并返回
Rd(keystring,timeouttime.Duration)interface{}//读取一个key,如果key不存在阻塞,等待key存在或者超时
}
typeMapstruct{
cmap[string]*entry
rmx*sync.RWMutex
}
typeentrystruct{
chchanstruct{}
valueinterface{}
isExistbool
}
func(m*Map)Out(keystring,valinterface{}){
m.rmx.Lock()
deferm.rmx.Unlock()
ife,ok:=m.c[key];ok{
e.value=val
e.isExist=true
close(e.ch)
}else{
e=&entry{ch:make(chanstruct{}),isExist:true,value:val}
m.c[key]=e
close(e.ch)
}
}
func(m*Map)Rd(keystring,timeouttime.Duration)interface{}{
m.rmx.Lock()
ife,ok:=m.c[key];ok&&e.isExist{
m.rmx.Unlock()
returne.value
}elseif!ok{
e=&entry{ch:make(chanstruct{}),isExist:false}
m.c[key]=e
m.rmx.Unlock()
fmt.Println("协程阻塞->",key)
select{
case<-e.ch:
returne.value
case<-time.After(timeout):
fmt.Println("协程超时->",key)
returnnil
}
}else{
m.rmx.Unlock()
fmt.Println("协程阻塞->",key)
select{
case<-e.ch:
returne.value
case<-time.After(timeout):
fmt.Println("协程超时->",key)
returnnil
}
}
}
                            
查看完整回答
反对 回复 2019-04-27
  • 2 回答
  • 0 关注
  • 489 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信