引用计数资源的线程安全映射



关于管理资源集合,这些资源是:

  1. 可通过全局列表(例如哈希映射(按名称访问
  2. 从多个线程并发访问
  3. ref-counted(Golang缺乏"弱引用";见
    https://groups.google.com/forum/#!topic/golang-nuts/PYWxjT2v6ps(

例:

var theList tMap // global
// in thread A, B, C etc
aThing := theList.ref("aThing") // if exists then refcount++, else insert
// use aThing
theList.unref("aThing") // refcount--, if 0 then remove

编辑:我希望为此找到推荐的模式,但没有任何结果。所以我想出了这个:

type tMap struct {
set map[string]*tMapSet
updt sync.RWMutex
}
type tMapSet struct {
...
refcount int32
}
func (o *tMap) ref(iId string) *tMapSet {
o.updt.RLock()
aSet := o.set[iId]
if aSet != nil {
atomic.AddInt32(&aSet.refcount, 1)
}
o.updt.RUnlock()
if aSet == nil {
o.updt.Lock()
if aTemp := o.set[iId]; aTemp != nil {
aSet = aTemp
aSet.refcount++
} else {
aSet = &tMapSet{refcount:1}
o.set[iId] = aSet
}
o.updt.Unlock()
}
return aSet
}
func (o *tMap) unref(iId string) {
o.updt.RLock()
aSet := o.set[iId]
aN := atomic.AddInt32(&aSet.refcount, -1) // crash if set[iId] not found
o.updt.RUnlock()
if aN == 0 {
o.updt.Lock()
if aSet.refcount == 0 {
delete(o.set, iId)
}
o.updt.Unlock()
}
}

建议提高上述内容的清晰度或简洁性?

只需将映射包装在互斥锁中即可保护访问(如果大量读取和少量写入,您也可以使用 RWMutex,可能数据也应该存储具体类型(。像这样的东西用几种方法就可以了:

type MagicMap struct {
sync.Mutex
data   map[string]interface{}
counts map[string]int
}
func (m MagicMap) Get(key string) interface{} {
m.Lock()
defer m.Unlock()
return m.data[key]
}
func (m MagicMap) Add(key string, value interface{}) {
m.Lock()
m.data[key] = value
m.counts[key] = m.counts[key] + 1
m.Unlock()
}
func (m MagicMap) Remove(key string) {
m.Lock()
count := m.counts[key]
count -= 1
if count < 1 {
delete(m.data, key)
delete(m.counts, key)
} else {
m.counts[key] = count
}
m.Unlock()
}

这是未经测试的,编写速度很快,并且可能有问题,但希望能为您提供尝试的方向。如果你愿意,你可以只有一个带有map[mystruct]int的地图来存储结构和计数。该示例具有单独的键和值。

https://play.golang.org/p/9k1lNRpqua

下面是使用互斥锁保护映射访问的另一个示例:

https://gobyexample.com/mutexes

您也可以使用新的同步。Go 1.9 中的映射,但它比仅使用互斥锁慢。

最新更新