동시 액세스가있는지도
동시 액세스가있는 프로그램에서 맵을 사용할 때 값 을 읽기 위해 함수에서 뮤텍스를 사용할 필요가 있습니까?
여러 독자, 작성자 없음은 괜찮습니다.
https://groups.google.com/d/msg/golang-nuts/HpLWnGTp-n8/hyUYmnWJqiQJ
한 명의 작가, 어떤 독자도 괜찮습니다. (그렇지 않으면지도는 그다지 좋지 않을 것입니다.)
그렇지 않으면 작성자가 하나 이상 있고 작성자 또는 독자가 하나 이상 있으면 모든 독자 와 작성자가 동기화를 사용하여 맵에 액세스해야합니다. 뮤텍스가이를 위해 잘 작동합니다.
sync.Map
2017 년 4 월 27 일자로 Go 마스터에 병합되었습니다.
이것은 우리 모두가 기다려 왔던 동시지도입니다.
https://github.com/golang/go/blob/master/src/sync/map.go
나는 귀하의 질문에 대답 이 며칠 전 레딧 스레드를 :
Go에서지도는 스레드로부터 안전하지 않습니다. 또한, 예를 들어 동일한 데이터를 쓰는 다른 고 루틴이있는 경우 (동시에) 데이터를 읽기 위해 잠금이 필요합니다.
의견에 대한 설명으로 판단하면 setter 기능도있을 것입니다. 질문에 대한 대답은 예입니다. 뮤텍스로 읽기를 보호해야합니다. RWMutex 를 사용할 수 있습니다 . 예를 들어 내가 작성한 (실제로 reddit 스레드에 링크 된) 테이블 데이터 구조의 구현 소스 (백그라운드 맵 사용)를 볼 수 있습니다.
당신이 사용할 수있는 동시지도를 당신을 위해 동시성 고통을 처리 할 수 있습니다.
// 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")
작가가 한 명뿐이라면 원자 값을 사용하여 벗어날 수 있습니다. 다음은 https://golang.org/pkg/sync/atomic/#example_Value_read 에서 수정되었습니다 (원본은 쓰기를 보호하기 위해 잠금을 사용하므로 여러 작성자를 지원함)
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.
}
대신 Go 동시성 모델을 사용하지 않는 이유는 간단한 예입니다.
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
}
내 간단한 구현 :
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
}
참고 URL : https://stackoverflow.com/questions/11063473/map-with-concurrent-access
'IT Share you' 카테고리의 다른 글
Entity Framework 4에서 기본적으로 지연로드 비활성화 (0) | 2020.12.02 |
---|---|
스 니펫에서 $ 문자 이스케이프 (0) | 2020.12.02 |
왜 그리고 어떻게 고치는가? (0) | 2020.12.02 |
텍스트 필드의 텍스트 삭제 UI 테스트 (0) | 2020.12.02 |
뒤로 버튼을 클릭 할 때 캐시에서 Safari로드 방지 (0) | 2020.12.02 |