SYNOPSIS #include <pthread.h> int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
func (cache *Cache) Get(key string, keyType int) *string {
if keyType == KEY_TYPE_DOMAIN {
key = "#" + key
} else {
key = "=" + key
}
cache.mutex.Lock()
item, existed := cache.dict[key]
if !existed {
item = &cacheItem{}
item.key = &key
item.waitQueue = list.New()
cache.dict[key] = item
}
cache.mutex.Unlock()
conf := config.GetConfig()
lastGet := getCurMs()
item.mutex.Lock()
item.lastGet = lastGet
if item.init { // 已存在并且初始化
defer item.mutex.Unlock()
return item.value
}
// 未初始化,排队等待结果
wait := waitItem{}
wait.wait_chan = make(chan *string, 1)
item.waitQueue.PushBack(&wait)
item.mutex.Unlock()
// 新增key, 启动goroutine获取初始值
if !existed {
go cache.initCacheItem(item, keyType)
}
timer := time.NewTimer(time.Duration(conf.Cache_waitTime) * time.Millisecond)
var retval *string = nil
// 等待初始化完成
select {
case retval = <- wait.wait_chan:
case <- timer.C:
}
return retval
} // 一旦标记为init, 后续请求将不再操作waitQueue
item.mutex.Lock()
item.value = newValue
item.init = true
item.expire = expire
item.mutex.Unlock()
// 唤醒所有排队者
waitQueue := item.waitQueue
for elem := waitQueue.Front(); elem != nil; elem = waitQueue.Front() {
wait := elem.Value.(*waitItem)
wait.wait_chan <- newValue
waitQueue.Remove(elem)
} 首先,锁住key,标记init=true,并赋值value,并释放锁。此后的请求,都可以立即返回,无需排队。
之后,因为init=true已被标记,此刻再也有没有请求会修改waitQueue,所以无需加锁,直接遍历队列,通知其中的每个chan。
最后
这样就实现了带超时的条件变量效果,实际上我的场景是一个broadcast的cond例子,大家可以参照思路实现自己想要的效果,活学活用。
以上就是实例讲解golang模拟实现带超时的信号量的详细内容,更多请关注Gxl网其它相关文章!
查看更多关于实例讲解golang模拟实现带超时的信号量的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did84473