本期分享:
1.sync.Map的原理和使用方式
2.實現有序的Map
sync.Map的原理和使用方式
sync.Map的底層結構是通過讀寫分離和無鎖讀設計實現高并發安全:
1)雙存儲結構:
包含原子化的 read
(只讀緩存,無鎖快速訪問)和加鎖的 dirty
(寫入緩沖區)
2)讀優先:
讀取時先嘗試無鎖訪問 read
,未命中時加鎖訪問 dirty
并記錄未命中次數
3)動態升級:
當未命中次數超過 dirty
長度時,將 dirty
原子替換為新的 read
4)延遲刪除:
刪除操作僅標記數據狀態(expunged
),實際清理在 dirty
升級時批量處理
5)值原子化:
通過 entry
指針的原子操作實現值更新的無鎖化,適用于讀多寫少的高并發場景。
部分源碼:
type Map struct {mu sync.Mutex // 保護 dirty 操作read atomic.Value // 只讀緩存(atomic 訪問)dirty map[interface{}]*entry // 寫入緩沖區misses int // read 未命中計數器
}type entry struct {p unsafe.Pointer // 可能的狀態:nil, expunged, 有效指針
}
Go 語言標準庫中的 sync.map
專為以下場景優化:
- 讀多寫少(98% 讀操作)
- 動態鍵空間(頻繁創建/刪除鍵)
- 需要保證并發安全
性能對比測試: 測試場景為4核CPU環境下并發讀寫
實現方式 | 100萬次讀/寫 (ns/op) | 內存占用 (MB) |
---|---|---|
map+sync.RWMutex | 420 | 32 |
sync.Map | 85 | 28 |
實現有序的map
在Go語言中,標準庫的map
是無序的,但可以通過組合數據結構實現有序映射。以下是幾種常見實現方案,根據需求選擇最適合的方式:
方案一:維護插入順序(鏈表法)
package mainimport"fmt"type OrderedMap struct {items map[interface{}]interface{}order []interface{}
}func NewOrderedMap() *OrderedMap {return &OrderedMap{items: make(map[interface{}]interface{}),order: make([]interface{}, 0),}
}func (m *OrderedMap) Set(key, value interface{}) {if _, exists := m.items[key]; !exists {m.order = append(m.order, key)}m.items[key] = value
}func (m *OrderedMap) Get(key interface{}) (interface{}, bool) {val, exists := m.items[key]return val, exists
}func (m *OrderedMap) Delete(key interface{}) {delete(m.items, key)// 重建順序切片(簡單實現,實際可用更高效方式)newOrder := make([]interface{}, 0, len(m.order)-1)for _, k := range m.order {if k != key {newOrder = append(newOrder, k)}}m.order = newOrder
}func (m *OrderedMap) Iterate() {for _, key := range m.order {fmt.Printf("%v: %v\n", key, m.items[key])}
}
方案二:排序映射(使用sort包)
package mainimport ("fmt""sort"
)type SortedMap struct {keys []intitems map[int]string
}func NewSortedMap() *SortedMap {return &SortedMap{keys: make([]int, 0),items: make(map[int]string),}
}func (m *SortedMap) Set(key int, value string) {if _, exists := m.items[key]; !exists {m.keys = append(m.keys, key)sort.Ints(m.keys) // 保持有序}m.items[key] = value
}func (m *SortedMap) Get(key int) (string, bool) {val, exists := m.items[key]return val, exists
}func (m *SortedMap) Iterate() {for _, key := range m.keys {fmt.Printf("%d: %s\n", key, m.items[key])}
}
方案三:使用第三方庫(推薦)
import "github.com/emirpasic/gods/maps/treemap"func main() {// 自然排序m := treemap.NewWithIntComparator()m.Put(1, "one")m.Put(3, "three")m.Put(2, "two")// 迭代器it := m.Iterator()for it.Next() {fmt.Printf("%d: %s\n", it.Key(), it.Value())}// 反向迭代rit := m.ReverseIterator()for rit.Next() {fmt.Printf("%d: %s\n", rit.Key(), rit.Value())}
}
本篇結束~