当前位置:网站首页>Source code analysis of golang map concurrent read / write problem
Source code analysis of golang map concurrent read / write problem
2022-06-27 19:56:00 【Lynalmost】
map Introduction and problem description
map It's mainly used to store kv data , The bottom layer uses the open chain method to eliminate conflicts hashtable, It has an automatic capacity expansion mechanism . Use map The most convenient thing is that you can O(1) A quick query ( at present slice No query interface is provided , You can only write your own algorithm to determine whether an element exists ).
map Although easy to use , But it may not apply .
however map There is a very deadly pit , In a concurrent scenario , Concurrent reading / Writing may occur fatal error:concurrent map read and map write
Error of , Just beginning to use map At the time of the naive that as long as not the same key Concurrent operation is OK , But it's a reality . There may be no problem when the concurrency is very small during testing ( Just lucky ), A large amount of concurrency will cause problems .
But not in all scenarios map It's not safe
This is a golang Official documents of , As mentioned above, as long as there is an update operation ,map It's non thread safe , But if the usage scenario is just concurrent reading , Write not involved / Delete operation , So it is concurrency safe .
Source code analysis
Definition
map head in flags Field , Recorded the current map Some states of , among hashWriting
Is to cause concurrent reading and writing map Wrong report “ The culprit ”.
// A header for a Go map.
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
// Make sure this stays in sync with the compiler's definition.
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
extra *mapextra // optional fields
}
// flags
iterator = 1 // there may be an iterator using buckets
oldIterator = 2 // there may be an iterator using oldbuckets
hashWriting = 4 // a goroutine is writing to the map
sameSizeGrow = 8 // the current map growth is to a new map of the same size
write in
- towards map The new element in the will eventually call
mapassign
function , It will be checked before the new operationflags
OfhashWriting
Whether a is 1, by 1 May be an error . - After passing the inspection, the position will be set as 1, The tag is currently being written .
- After writing, set the position to 0
// Like mapaccess, but allocates a slot for the key if it is not present in the map.
func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
...
if h.flags&hashWriting != 0 {
throw("concurrent map writes")
}
hash := t.hasher(key, uintptr(h.hash0))
// Set hashWriting after calling t.hasher, since t.hasher may panic,
// in which case we have not actually done a write.
h.flags ^= hashWriting
...
done:
if h.flags&hashWriting == 0 {
throw("concurrent map writes")
}
h.flags &^= hashWriting
...
Read
The process of reading data is relatively simple , Before reading, determine whether there is a setting , If the verification is passed, the read operation can be performed , The read operation will not be set .
That's why , If one map Initialized ok after , As long as there is no addition, deletion or modification , Read the newspaper incorrectly at the same time .
// mapaccess1 returns a pointer to h[key]. Never returns nil, instead
// it will return a reference to the zero object for the elem type if
// the key is not in the map.
// NOTE: The returned pointer may keep the whole map live, so don't
// hold onto it for very long.
func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
...
if h.flags&hashWriting != 0 {
throw("concurrent map read and map write")
}
...
}
Conclusion
1. After reading the source code , I found it was like a read-write lock , But it doesn't cause any blockage , If there's a problem, it's direct throw
.
2. If you do initialize once , Always read concurrently , You can use it boldly map.
Common solutions
1. Self lock read .
2. Use sync.map replace ( I've seen some principles , Locking is implemented when writing data ; Using space for time , Use two hash structures to store Map, There is a layer of cache , Speed up data reading .)
3. Use 2D slice instead of , take key and index Mapping .
# If there is any misunderstanding or misunderstanding ~ Welcome to correct ~~
边栏推荐
- Redis cluster Series III
- UE4-Actor基础知识
- Making single test so simple -- initial experience of Spock framework
- Array exercises follow up
- 可靠的分布式锁 RedLock 与 redisson 的实现
- Buzzer experiment based on stm32f103zet6 library function
- The Fifth Discipline: the art and practice of learning organization
- 从指令交读掌握函数调用堆栈详细过程
- MASS幸运哈希游戏系统开发丨冲突解决方法(代码分析)
- Bit.Store:熊市漫漫,稳定Staking产品或成主旋律
猜你喜欢
MySQL初学者福利
SQL Server - window function - solve the problem of filtering consecutive n records
数仓的字符截取三胞胎:substrb、substr、substring
429- binary tree (108. convert the ordered array into a binary search tree, 538. convert the binary search tree into an accumulation tree, 106. construct a binary tree from the middle order and post o
crontab的学习随笔
爬取国家法律法规数据库
Blink SQL内置函数大全
在线文本按行批量反转工具
【登录界面】
Doctoral Dissertation of the University of Toronto - training efficiency and robustness in deep learning
随机推荐
The Fifth Discipline: the art and practice of learning organization
OpenSSL client programming: SSL session failure caused by an obscure function
作用域-Number和String的常用Api(方法)
UE4实现长按功能
Rust 中的枚举和控制流运算
【登录界面】
刷题笔记-树(Easy)-更新中
华大单片机KEIL报错_WEAK的解决方案
这个是和数据采集一样,可以定义一个参数为上个月或者前一天,然后在sql中使用这个参数吗?
数智化进入“深水区”,数据治理是关键
308. 二维区域和检索 - 可变 线段树/哈希
Online text batch inversion by line tool
一对一关系
A simple calculation method of vanishing point
Erreur Keil de Huada Single Chip Computer La solution de Weak
1025 PAT Ranking
shell脚本常用命令(三)
ABAP-CL_OBJECT_COLLECTION工具类
1028 List Sorting
高收益银行理财产品在哪里看?