小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《如何在使用指针变量时消除数据竞争》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!
问题内容这里有一些起始代码,
func (chm *concurrenthashmap) nfetchworker() {
for {
key := <-nfetchworkerpipe
chm.mu.rlock()
data := chm.data[string(key)]
chm.mu.runlock()
if data.isusingnfetch {
chm.mu.lock()
*(chm.data[string(key)].nfetch)--
chm.mu.unlock()
}
}
}
go nfetchworker()
struct concurrenthashmap 看起来像这样,
type concurrenthashmap struct {
data map[string]datablock
mu sync.rwmutex
}
结构 datablock 看起来像这样,
type datablock struct {
...
nfetch *int32
isusingnfetch bool
...
}
现在,当我尝试在启用竞赛标志的情况下运行测试时。我明白了,
write at 0x00c00012e310 by goroutine 8:
(*concurrenthashmap).nfetchworker()
行号指向该行。
*(chm.data[string(key)].nfetch)--
但是,当我不在 datablock.nfetch 中使用指针时,我不会遇到此问题。 但如果我这样做,我就失去了直接从映射对 nfetch 进行更改的能力,而无需将一个全新的结构对象重新分配给映射中的哈希值,这在计算上相对昂贵。我想更改 nfetch 的值,而无需为一个小更改再次重新分配整个结构,同时不受数据争用的影响。有什么解决办法吗??
对 golang 相当陌生,我可能在这里做了一些非常愚蠢的事情,请随意指出。
更新:添加读写操作功能
func (chm *concurrenthashmap) get(key key) value {
chm.mu.rlock()
fetch, ok := chm.data[string(key)]
chm.mu.runlock()
if ok {
if checkvaluevalidity(&fetch) {
nfetchworkerpipe <- key
return fetch.value
} else {
chm.mu.lock()
delete(chm.data, string(key))
chm.mu.unlock()
}
}
return constants.nil
}
写操作
func (chm *ConcurrentHashMap) Insert(key Key, value Value, options Options) {
...
chm.mu.Lock()
chm.data[string(key)] = Block{
Value: value,
NFetch: nFetchOld,
Expiry: time.Now().Add(delay),
IsUsingNFetch: foundNFetch,
IsUsingExpiry: foundTTL,
mu: mutex,
}
chm.mu.Unlock()
}
正确答案
问题出在 checkvaluevalidity
中,您在其中访问 nfetch
而不锁定它。永远不要在没有锁定指针的情况下访问指针。
func checkvaluevalidity(value *block) bool {
if value.isusingexpiry && !value.expiry.after(time.now()) {
return false
}
if value.isusingnfetch && *(value.nfetch) <= 0 {
return false
}
return true
}
这段代码应该可以工作
func (chm *ConcurrentHashMap) Get(key Key) Value {
chm.mu.RLock()
fetch, ok := chm.data[string(key)]
isValid := CheckValueValidity(&fetch)
chm.mu.RUnlock()
if ok {
if isValid {
NFetchWorkerPipe <- key
return fetch.Value
} else {
chm.mu.Lock()
delete(chm.data, string(key))
chm.mu.Unlock()
}
}
return constants.NIL
}
今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注编程网公众号,一起学习编程~