Skip to content

Commit

Permalink
feat(go map): 添加go map如何知道读写冲突的文章
Browse files Browse the repository at this point in the history
  • Loading branch information
andywu1998 authored Oct 10, 2023
1 parent 47b7037 commit 378fa34
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions _posts/2023-10-10-go里的map是怎么判断并发读写的?.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# map如何知道自己被抢占
map的底层实现是hmap结构体,有一个叫flags的uint8类型字段。

下面这些常量表示flag每一个位的作用
```go
// 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
```

其中这里关于如何判断锁冲突的是hashWriting字段
##

```go
// 因为h.flags默认为0,所以hashWriting初始化应该为0,如果不为0说明其他goroutine在写
if h.flags&hashWriting != 0 {
fatal("concurrent map writes")
}
// 开始写,writing位置为1
h.flags ^= hashWriting
// 写之后判断,因为刚刚已经把writting置位1了,这里不应该为0,如果为0说明在写的过程中有人改过了。
if h.flags&hashWriting == 0 {
fatal("concurrent map writes")
}
// 恢复原状
h.flags &^= hashWriting
```


## 删除
```go
// 判断是否为0,如果不为0则fatal
if h.flags&hashWriting != 0 {
fatal("concurrent map writes")
}

// 开始删除,置为1
h.flags ^= hashWriting

// 如果等于0表示又其他go routine把它置为1了,fatal
if h.flags&hashWriting == 0 {
fatal("concurrent map writes")
}
// 恢复原状
h.flags &^= hashWriting
```

##
```go
// 读的时候只需要判断,不需要修改。
if h.flags&hashWriting != 0 {
fatal("concurrent map read and map write")
}
## 番外篇 &^ 运算
暂时找不到更多概念,只能写个demo看看。

```go
package main
import "fmt"
func test(testCases [][]int) {
for _, testCase := range testCases {
ret := testCase[0] &^ testCase[1]
fmt.Printf("%v &^ %v = %v\n", testCase[0], testCase[1], ret)
}
}
func main() {
testcase := [][]int{
{0, 0},
{0, 1},
{1, 0},
{1, 1},
}
test(testcase)
}
```

结果
```
0 &^ 0 = 0
0 &^ 1 = 0
1 &^ 0 = 1
1 &^ 1 = 0

```

0 comments on commit 378fa34

Please sign in to comment.