3 回答
TA贡献1811条经验 获得超4个赞
使用单程套餐。为该组声明一个包级变量:
var g singleflight.Group
使用以下代码获取值:
v, err, _ := g.Do(key, func() (interface{}, error) {
if !hasCachedValue(key) {
buildCacheValue(key)
}
return cachedValue(key), nil
})
if err != nil {
// handle error
}
x := v.(valueType) // assert to type returned by cachedValue
// do something with x
TA贡献1829条经验 获得超6个赞
这是一个简单的代码,可以完成您想要的操作。我测试了它,它工作没有问题。Go 竞争条件检查器没有检测到任何问题。
type Cache struct {
mtx sync.RWMutex
m map[KeyType]*CacheValue
}
type CacheValue struct {
val *ValueType
mtx sync.Mutex
}
func NewCache() *Cache {
return &Cache{m: make(map[KeyType]*CacheValue)}
}
func (c *Cache) Get(key KeyType) *ValueType {
c.mtx.RLock()
v := c.m[key]
c.mtx.RUnlock()
if v != nil {
v.mtx.Lock()
x := v.val
v.mtx.Unlock()
if x != nil {
return x
}
}
if v == nil {
c.mtx.Lock()
v = c.m[key]
if v == nil {
v = &CacheValue{}
c.m[key] = v
}
c.mtx.Unlock()
}
v.mtx.Lock()
if v.val == nil {
v.val = buildValue(key)
}
v.mtx.Unlock()
return v.val
}
TA贡献1900条经验 获得超5个赞
受到经常用于描述通道的乒乓球示例的启发,我们尝试了仅通道方法。球保存有关正在生成的密钥的状态,并且球在共享通道的请求之间传递:
import "time"
var table = make(chan map[string]chan bool)
func keeper() {
for {
ball := <- table
table <- ball
}
}
func getResource(key string) {
// Take ball from table
ball := <- table
if wait, ok := ball[key]; ok{
println("Somebody else working on " + key + ", waiting")
table <- ball
<- wait
} else {
println("I will build " + key)
ball[key] = make(chan bool)
// Throw away ball
table <- ball
// Building value
time.Sleep(time.Millisecond * 10)
println("I built value for " + key + "!")
// Clean up ball
ball = <- table
close(ball[key])
delete(ball, key)
table <- ball
}
println("Now value for " + key + " has been built")
}
func main(){
go keeper()
ball := make(map[string]chan bool)
table <- ball
key := "key"
go getResource(key)
go getResource(key)
go getResource(key)
time.Sleep(time.Second)
}
- 3 回答
- 0 关注
- 151 浏览
添加回答
举报