当你在并发访问程序中使用的地图,是否有任何需要使用互斥函数读取值?
Answer 1:
多的读者,没有作家是好的:
https://groups.google.com/d/msg/golang-nuts/HpLWnGTp-n8/hyUYmnWJqiQJ
一个作家,没有读者是好的。 (地图也不会有什么好的除外。)
否则,如果有至少一个作家和至少一个或者多个作家还是读者,那么所有的读者和作家必须使用同步进入地图。 互斥这个工作正常。
Answer 2:
sync.Map
已合并吴清源截至2017年4月27日。
这是我们都在等待的同时地图。
https://github.com/golang/go/blob/master/src/sync/map.go
https://godoc.org/sync#Map
Answer 3:
我回答你的问题这几天前reddit的线程:
在围棋,地图是不是线程安全的。 此外,数据需要即时对读,如果,例如,有可能是被写入相同的数据(同时,这是)另一个goroutine中锁定。
你澄清的评论来看,有将是二传功能也将回答你的问题是肯定的,你将不得不保护与互斥的读取; 您可以使用RWMutex 。 举一个例子,你可以看看源表中的数据结构的实施(在后台使用的地图),我写了(实际上是一个在reddit的螺纹连接)。
Answer 4:
你可以使用并发图来处理并发的痛苦你。
// Create a new map.
map := cmap.NewConcurrentMap()
// Add item to map, adds "bar" under key "foo"
map.Add("foo", "bar")
// Retrieve item from map.
tmp, ok := map.Get("foo")
// Checks if item exists
if ok == true {
// Map stores items as interface{}, hence we'll have to cast.
bar := tmp.(string)
}
// Removes item under key "foo"
map.Remove("foo")
Answer 5:
如果你只有一个作家,那么你也许可以逃脱使用原子值。 以下是从适合https://golang.org/pkg/sync/atomic/#example_Value_readMostly (原用锁来保护写作,所以支持多种作家)
type Map map[string]string
var m Value
m.Store(make(Map))
read := func(key string) (val string) { // read from multiple go routines
m1 := m.Load().(Map)
return m1[key]
}
insert := func(key, val string) { // update from one go routine
m1 := m.Load().(Map) // load current value of the data structure
m2 := make(Map) // create a new map
for k, v := range m1 {
m2[k] = v // copy all data from the current object to the new one
}
m2[key] = val // do the update that we need (can delete/add/change)
m.Store(m2) // atomically replace the current object with the new one
// At this point all new readers start working with the new version.
// The old version will be garbage collected once the existing readers
// (if any) are done with it.
}
Answer 6:
为什么不利用围棋并发模型代替,有一个简单的例子...
type DataManager struct {
/** This contain connection to know dataStore **/
m_dataStores map[string]DataStore
/** That channel is use to access the dataStores map **/
m_dataStoreChan chan map[string]interface{}
}
func newDataManager() *DataManager {
dataManager := new(DataManager)
dataManager.m_dataStores = make(map[string]DataStore)
dataManager.m_dataStoreChan = make(chan map[string]interface{}, 0)
// Concurrency...
go func() {
for {
select {
case op := <-dataManager.m_dataStoreChan:
if op["op"] == "getDataStore" {
storeId := op["storeId"].(string)
op["store"].(chan DataStore) <- dataManager.m_dataStores[storeId]
} else if op["op"] == "getDataStores" {
stores := make([]DataStore, 0)
for _, store := range dataManager.m_dataStores {
stores = append(stores, store)
}
op["stores"].(chan []DataStore) <- stores
} else if op["op"] == "setDataStore" {
store := op["store"].(DataStore)
dataManager.m_dataStores[store.GetId()] = store
} else if op["op"] == "removeDataStore" {
storeId := op["storeId"].(string)
delete(dataManager.m_dataStores, storeId)
}
}
}
}()
return dataManager
}
/**
* Access Map functions...
*/
func (this *DataManager) getDataStore(id string) DataStore {
arguments := make(map[string]interface{})
arguments["op"] = "getDataStore"
arguments["storeId"] = id
result := make(chan DataStore)
arguments["store"] = result
this.m_dataStoreChan <- arguments
return <-result
}
func (this *DataManager) getDataStores() []DataStore {
arguments := make(map[string]interface{})
arguments["op"] = "getDataStores"
result := make(chan []DataStore)
arguments["stores"] = result
this.m_dataStoreChan <- arguments
return <-result
}
func (this *DataManager) setDataStore(store DataStore) {
arguments := make(map[string]interface{})
arguments["op"] = "setDataStore"
arguments["store"] = store
this.m_dataStoreChan <- arguments
}
func (this *DataManager) removeDataStore(id string) {
arguments := make(map[string]interface{})
arguments["storeId"] = id
arguments["op"] = "removeDataStore"
this.m_dataStoreChan <- arguments
}
Answer 7:
我简单的实现:
import (
"sync"
)
type AtomicMap struct {
data map[string]string
rwLock sync.RWMutex
}
func (self *AtomicMap) Get(key string) (string, bool) {
self.rwLock.RLock()
defer self.rwLock.RUnlock()
val, found := self.data[key]
return val, found
}
func (self *AtomicMap) Set(key, val string) {
self.rwLock.Lock()
defer self.rwLock.Unlock()
self.data[key] = val
}
文章来源: Map with concurrent access