Go實作一個簡單可供並行程序存取的concurrent map。
Go的map不保證執行緒安全,即當多個goroutine程序存取通個資源時會發生race condition(資源競爭)導致非預期的結果,所以執行goroutine並行程式應限制map同步存取。
範例環境:
- Go 1.18
範例
使用sync.RWMutex
的讀/寫鎖在存取package level map變數m
上。
在get()
使用RWMutex.RLock()
、RWMutex.RUnLock()
允許多個goroutine並行讀取。
在put()
使用RWMutex.Lock()
、RWMutex.UnLock()
限制只能一個goroutine寫入。
main.go
package main
import (
"fmt"
"sync"
"time"
)
var rwmu sync.RWMutex
var m = map[int]int{}
func main() {
for i := 0; i < 10; i++ {
go put(i, i)
go func(k int) {
fmt.Println(get(k))
}(i)
}
time.Sleep(time.Second)
}
func get(k int) int {
rwmu.RLock()
defer rwmu.RUnlock()
v, ok := m[k]
if ok == false {
return -1
}
return v
}
func put(k int, v int) {
rwmu.Lock()
defer rwmu.Unlock()
m[k] = v
}
func size() int {
rwmu.RLock()
defer rwmu.RUnlock()
return len(m)
}
測試
可用go run -race main.go
確認是否有data race condition的情況。若把Mutex lock移除並執行可能發生以下錯誤
~/../go-demo$ go run -race main.go
-1
-1
-1
==================
WARNING: DATA RACE
Read at 0x00c00007e048 by goroutine 14:
main.get()
/../main.go:26 +0x58
main.main.func1()
/../main.go:17 +0x61
main.main.func3()
/..//main.go:18 +0x47
Previous write at 0x00c00007e048 by goroutine 13:
main.put()
/../main.go:36 +0x57
main.main.func2()
/../main.go:15 +0x47
Goroutine 14 (running) created at:
main.main()
/../main.go:16 +0x44
Goroutine 13 (running) created at:
main.main()
/../main.go:15 +0xb7
==================
...
沒有留言:
張貼留言