如何实现一个单子

问题描述 投票:1回答:3

我想用Go实现一个singleton。与普通的singleton不同的是,实例是在map结构中用不同的key实现的singleton。类似这样的代码。我不知道这段演示代码是否存在数据竞赛。

var instanceLock sync.Mutex
var instances map[string]string

func getDemoInstance(key string) string {
    if value, ok := instances[key]; ok {
        return value
    }
    instanceLock.Lock()
    defer instanceLock.Unlock()
    if value, ok := instances[key]; ok {
        return value
    } else {
        instances[key] = key + key
        return key + key
    }
}
go singleton instance
3个回答
1
投票

是的,有数据竞赛,你可以通过运行它来确认。go run -race main.go. 如果一个goroutine锁定并修改了地图,另一个goroutine可能会在锁定前读取地图。

你可以使用 sync.RWMutex 来锁定阅读,当只是阅读的时候(允许多个阅读者不互相阻挡)。

比如说

var (
    instancesMU sync.RWMutex
    instances   = map[string]string{}
)

func getDemoInstance(key string) string {
    instancesMU.RLock()
    if value, ok := instances[key]; ok {
        instancesMU.RUnlock()
        return value
    }

    instancesMU.RUnlock()

    instancesMU.Lock()
    defer instancesMU.Unlock()
    if value, ok := instances[key]; ok {
        return value
    }
    value := key + key
    instances[key] = value
    return value
}

0
投票

你也可以试试这个。sync.Map

Map就像Go的map[interface{}]interface{}一样,但对于多个goroutine的并发使用是安全的,不需要额外的锁定或协调。加载、存储和删除都是以摊开的恒定时间运行的。

Map类型针对两种常见的用例进行了优化。(1)当一个给定的键的条目只被写入一次,但却被多次读取,比如在只会增长的缓存中;或者(2)当多个goroutine读取、写入和覆盖不相干键集的条目时。

在这两种情况下,与Go map与单独的Mutex或RWMutex配对相比,使用Map可以显著减少锁的争用。

注意事项: 在第三段中,它提到为什么使用 sync.Map 是有益的,而不是简单地将Go Map与之搭配使用。sync.RWMutex.

所以这完全符合你的情况吧?


0
投票

回答得有点晚,总之这个应该能帮到你。https:/github.comashwinshirvaapitreemasterdpsingleton.

这显示了两种实现singleton的方法。

  1. 使用 sync.Mutex
  2. 使用 sync.Once
© www.soinside.com 2019 - 2024. All rights reserved.