Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Map 具有并发访问的映射_Map_Go_Mutex - Fatal编程技术网

Map 具有并发访问的映射

Map 具有并发访问的映射,map,go,mutex,Map,Go,Mutex,当您在具有并发访问的程序中使用映射时,是否需要在函数中使用互斥来读取值?多个读取器,没有写入器是可以的: 一个作家,没有读者是可以的。(否则地图就不会有多好了。) 否则,如果至少有一个writer和至少一个writer或reader,则所有读卡器和写卡器必须使用同步来访问地图。互斥器可以很好地实现这一点。多个读卡器,没有写卡器是可以的: 一个作家,没有读者是可以的。(否则地图就不会有多好了。) 否则,如果至少有一个writer和至少一个writer或reader,则所有读卡器和写卡器必须使用

当您在具有并发访问的程序中使用映射时,是否需要在函数中使用互斥来读取值?

多个读取器,没有写入器是可以的:

一个作家,没有读者是可以的。(否则地图就不会有多好了。)


否则,如果至少有一个writer和至少一个writer或reader,则所有读卡器写卡器必须使用同步来访问地图。互斥器可以很好地实现这一点。

多个读卡器,没有写卡器是可以的:

一个作家,没有读者是可以的。(否则地图就不会有多好了。)


否则,如果至少有一个writer和至少一个writer或reader,则所有读卡器写卡器必须使用同步来访问地图。互斥可以很好地解决这个问题。

几天前我在reddit线程中回答了您的问题:

在围棋中,地图不是线程安全的。此外,数据甚至需要锁定 例如,如果有另一个goroutine是 写入相同的数据(即并发)


从您在评论中的澄清判断,也将有setter函数,您的问题的答案是肯定的,您必须使用互斥来保护您的读取;你可以用一个。例如,您可以查看我编写的表数据结构(在后台使用映射)的实现(实际上是在reddit线程中链接的一个)。几天前,我在reddit线程中回答了您的问题:

在围棋中,地图不是线程安全的。此外,数据甚至需要锁定 例如,如果有另一个goroutine是 写入相同的数据(即并发)

从您在评论中的澄清判断,也将有setter函数,您的问题的答案是肯定的,您必须使用互斥来保护您的读取;你可以用一个。例如,您可以查看我编写的表数据结构(在后台使用映射)的实现(实际上是在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")
您可以使用它来处理并发问题

// 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")

如果您只有一个编写器,那么您可能不需要使用原子值。以下内容改编自(原版使用锁来保护写入,因此支持多个写入程序)


如果您只有一个编写器,那么您可能不需要使用原子值。以下内容改编自(原版使用锁来保护写入,因此支持多个写入程序)


自2017年4月27日起,
sync.Map
已合并为Go master

这是我们一直在等待的并发映射


sync.Map
自2017年4月27日起已合并为Go master

这是我们一直在等待的并发映射


为什么没有使用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
}
类型数据管理器结构{
/**这包含到已知数据存储的连接**/
m_数据存储映射[字符串]数据存储
/**该通道用于访问数据存储地图**/
m_dataStoreChan chan map[string]接口{}
}
func newDataManager()*数据管理器{
dataManager:=新建(dataManager)
dataManager.m_dataStores=make(映射[字符串]数据存储)
dataManager.m_dataStoreChan=make(chan-map[string]接口{},0)
//并发性。。。
go func(){
为了{
挑选{

案例op:=为什么没有使用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
}
类型数据管理器结构{
/**这包含到已知数据存储的连接**/
m_数据存储映射[字符串]数据存储
/**该通道用于访问数据存储地图**/
m_dataStoreChan chan map[string]接口{}
}
func newDataManager()*数据管理器{
dataManager:=新建(dataManager)
dataManager.m_dataStores=make(映射[字符串]数据存储)
dataManager.m_dataStoreChan=make(chan-map[string]接口{},0)
//并发性。。。
go func(){
为了{
挑选{

case op:=如果它是一个严格的只读映射,则不需要互斥。我不太清楚,因为将有函数来设置和获取值。如果它是一个严格的只读映射,则不需要互斥。我不太清楚,因为将有函数来设置和获取值。通常使用完整的读写器锁来设置值是浪费时间的与Map一样快的资源访问速度可以请您详细说明一下吗?什么更合适?RW锁适用于具有大量争用的资源,但它们比互斥锁有更多的开销。Map get/Set足够快,程序可能不会有足够的争用,从而使更复杂的锁比简单的mu提供更好的吞吐量谢谢你的澄清。你有什么论文/文章可以推荐吗?但是,这篇文章的并发部分建议同步。RWMutexit通常是浪费资源的,使用一个完整的读写器锁来访问一个和地图一样快的资源。你能详细说明一下吗?什么更合适?RW锁很好对于具有大量争用的资源,但它们的开销比互斥体大。Map get/Set速度足够快,程序可能不会有足够的争用,从而使更复杂的锁比简单的互斥体提供更好的吞吐量。感谢您的澄清。您有任何关于这一问题的论文/文章可以推荐吗?但是,这篇文章的并发部分建议使用sync.rwmutexthing这样的东西,这就是为什么我不能认真对待go“不需要泛型”这一概念。这一概念不是说go“不需要泛型”,而是“目前没有干净的方法来实现泛型,我们需要进一步思考”例如,C++生成所有可能组合的代码。