go在並發情況下使用map


 

兩種方式解決並發訪問map

  • 讀寫鎖實現並發安全Map
  • sync.Map

 

讀寫鎖實現並發安全Map

並發訪問map是不安全的。
所以如果希望在多協程中並發訪問map,必須提供某種同步機制,一般情況下通過讀寫鎖sync.RWMutex實現對map的並發訪問控制,將map和sync.RWMutex封裝一下,可以實現對map的安全並發訪問。

package main

import (
	"fmt"
	"sync"
)
// M
type M struct {
	Map    map[interface{}]interface{}
	lock *sync.RWMutex
}
// Set ...
func (m *M) Set(key interface{}, value interface{}) {
	m.lock.RLock()
	defer m.lock.RUnlock()
	m.Map[key] = value
}
// Get ...
func (m *M) Get(key interface{}) interface{} {
	m.lock.Lock()
	defer m.lock.Unlock()
	return m.Map[key]
}



func main() {
	Map := &M{
		make(map[interface{}]interface{}),
		new(sync.RWMutex),
	}

	Map.Set(2,"2323")
	Map.Set("hello",343)
	fmt.Println(Map.Get(2))
	fmt.Println(Map.Get("hello"))
}

 

sync.Map

go1.9之后加入了支持並發安全的Map sync.Map。

sync.Map 通過一份只使用原子操作的數據和一份冗余了只讀數據的加鎖數據實現一定程度上的讀寫分離,使得大多數讀操作和更新操作是原子操作,寫入新數據才加鎖的方式來提升性能。
1、Store 存 key,value

2、LoadOrStore 取&存

3、Load 取key對應的value

4、Range 遍歷所有的key,value

5、Delete 刪除key,及其value

package main
 
import (
	"fmt"
	"sync"
)
 
func main() {
	var m sync.Map
 
	//Store
	m.Store(1,"a")
	m.Store(2,"b")
 
	//LoadOrStore
	//若key不存在,則存入key和value,返回false和輸入的value
	v,ok := m.LoadOrStore("1","aaa")
	fmt.Println(ok,v) //false aaa
 
	//若key已存在,則返回true和key對應的value,不會修改原來的value
	v,ok = m.LoadOrStore(1,"aaa")
	fmt.Println(ok,v) //false aaa
 
	//Load
	v,ok = m.Load(1)
	if ok{
		fmt.Println("it's an existing key,value is ",v)
	} else {
		fmt.Println("it's an unknown key")
	}
 
	//Range
	//遍歷sync.Map, 要求輸入一個func作為參數
	f := func(k, v interface{}) bool {
		//這個函數的入參、出參的類型都已經固定,不能修改
		//可以在函數體內編寫自己的代碼,調用map中的k,v
 
			fmt.Println(k,v)
			return true
		}
	m.Range(f)
 
	//Delete
	m.Delete(1)
	fmt.Println(m.Load(1))
 
}

 

refer:

sync.Map vs Map with lock

Go 1.9 sync.Map揭秘

golang 並發安全Map以及分段鎖的實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM