欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > Go实现阻塞读且并发安全的map

Go实现阻塞读且并发安全的map

2024/10/24 7:22:31 来源:https://blog.csdn.net/linzhongshu/article/details/139378653  浏览:    关键词:Go实现阻塞读且并发安全的map

GO里面MAP如何实现key不存在 get操作等待 直到key存在或者超时,保证并发安全,且需要实现以下接口:

type sp interface {Out(key string, val interface{})  //存入key /val,如果该key读取的goroutine挂起,则唤醒。此方法不会阻塞,时刻都可以立即执行并返回Rd(key string, timeout time.Duration) interface{}  //读取一个key,如果key不存在阻塞,等待key存在或者超时
}

解析:

看到阻塞协程第一个想到的就是channel,题目中要求并发安全,那么必须用锁,还要实现多个goroutine读的时候如果值不存在则阻塞,直到写入值,那么每个键值需要有一个阻塞goroutinechannel

实现如下:

type Map struct {c   map[string]*entryrmx *sync.RWMutex
}
type entry struct {ch      chan struct{}value   interface{}isExist bool
}func (m *Map) Out(key string, val interface{}) {m.rmx.Lock()defer m.rmx.Unlock()if e, ok := m.c[key]; ok {e.value = vale.isExist = trueclose(e.ch)} else {e = &entry{ch: make(chan struct{}), isExist: true,value:val}m.c[key] = eclose(e.ch)}
}func (m *Map) Rd(key string, timeout time.Duration) interface{} {m.rmx.Lock()if e, ok := m.c[key]; ok && e.isExist {m.rmx.Unlock()return e.value} else if !ok {e = &entry{ch: make(chan struct{}), isExist: false}m.c[key] = em.rmx.Unlock()fmt.Println("协程阻塞 -> ", key)select {case <-e.ch:return e.valuecase <-time.After(timeout):fmt.Println("协程超时 -> ", key)return nil}} else {m.rmx.Unlock()fmt.Println("协程阻塞 -> ", key)select {case <-e.ch:return e.valuecase <-time.After(timeout):fmt.Println("协程超时 -> ", key)return nil}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com