并发地图迭代和地图写入 RLock/RUnlock
concurrent map iteration and map write with RLock/RUnlock
不确定为什么我的程序会遇到
的错误
concurrent map iteration and map write
我把RLock()/mv.RUnlock()
放在这里
for k := range confirmed_slot {
keys = append(keys, k)
}
这是我的完整测试程序
package main
import (
"container/list"
"fmt"
"math/rand"
"sync"
"time"
"github.com/twotwotwo/sorts/sortutil"
)
var (
queue = list.New()
confirmed_slot = map[uint64]string{}
mv sync.RWMutex
)
func FetchConfirmedSlots() {
ticker := time.NewTicker(1 * time.Second)
for {
mv.RLock()
rand.Seed(time.Now().UnixNano())
r := randSeq(10)
slot := rand.Uint64()
confirmed_slot[slot] = r
queue.PushBack(slot)
fmt.Println("Slot Added " , slot , " ", len(confirmed_slot))
mv.RUnlock()
<-ticker.C
}
}
func RemoveItemSlotFull() {
ticker := time.NewTicker(1 * time.Millisecond)
for {
if queue.Len() == 150 {
mv.RLock()
front := queue.Front()
queue.Remove(front)
v, ok := front.Value.(uint64)
if ok {
fmt.Println("Slot deleted " , v)
delete(confirmed_slot, v)
fmt.Println("Slot deleted " , v , " ", len(confirmed_slot))
}
mv.RUnlock()
}
<-ticker.C
}
}
func GetLatestSlot() {
ticker := time.NewTicker(1 * time.Second)
for {
mv.RLock()
if queue.Len() >0 {
back := queue.Back()
fmt.Println("Slot Fetched ", back.Value , " ",len(confirmed_slot))
}
mv.RUnlock()
<-ticker.C
}
}
func GetConfirmedBlockHashes() {
ticker := time.NewTicker(1 * time.Second)
for {
if queue.Len() >0 {
mv.RLock()
back := queue.Back()
v, _ := back.Value.(uint64)
keys := make([]uint64, 0, len(confirmed_slot))
for k := range confirmed_slot {
keys = append(keys, k)
}
n := sortutil.SearchUint64s(keys,v)
fmt.Println("Found ... " , n, true)
mv.RUnlock()
}
<-ticker.C
}
}
func main() {
go FetchConfirmedSlots()
go RemoveItemSlotFull()
go GetLatestSlot()
go GetConfirmedBlockHashes()
select {}
}
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
尝试 mv.Lock()
和 mv.Unlock()
,而不是 mv.RLock()
和 mv.RUnlock()
。您正在写信给 confirmed_slot
.
Rlock()
和 RUnlock()
用于读取 - 它们允许多个线程同时读取,只要 none 正在写入。
Lock()
和 Unlock()
将确保一次只有一个线程持有锁,无论它是读还是写。
不确定为什么我的程序会遇到
的错误concurrent map iteration and map write
我把RLock()/mv.RUnlock()
放在这里
for k := range confirmed_slot {
keys = append(keys, k)
}
这是我的完整测试程序
package main
import (
"container/list"
"fmt"
"math/rand"
"sync"
"time"
"github.com/twotwotwo/sorts/sortutil"
)
var (
queue = list.New()
confirmed_slot = map[uint64]string{}
mv sync.RWMutex
)
func FetchConfirmedSlots() {
ticker := time.NewTicker(1 * time.Second)
for {
mv.RLock()
rand.Seed(time.Now().UnixNano())
r := randSeq(10)
slot := rand.Uint64()
confirmed_slot[slot] = r
queue.PushBack(slot)
fmt.Println("Slot Added " , slot , " ", len(confirmed_slot))
mv.RUnlock()
<-ticker.C
}
}
func RemoveItemSlotFull() {
ticker := time.NewTicker(1 * time.Millisecond)
for {
if queue.Len() == 150 {
mv.RLock()
front := queue.Front()
queue.Remove(front)
v, ok := front.Value.(uint64)
if ok {
fmt.Println("Slot deleted " , v)
delete(confirmed_slot, v)
fmt.Println("Slot deleted " , v , " ", len(confirmed_slot))
}
mv.RUnlock()
}
<-ticker.C
}
}
func GetLatestSlot() {
ticker := time.NewTicker(1 * time.Second)
for {
mv.RLock()
if queue.Len() >0 {
back := queue.Back()
fmt.Println("Slot Fetched ", back.Value , " ",len(confirmed_slot))
}
mv.RUnlock()
<-ticker.C
}
}
func GetConfirmedBlockHashes() {
ticker := time.NewTicker(1 * time.Second)
for {
if queue.Len() >0 {
mv.RLock()
back := queue.Back()
v, _ := back.Value.(uint64)
keys := make([]uint64, 0, len(confirmed_slot))
for k := range confirmed_slot {
keys = append(keys, k)
}
n := sortutil.SearchUint64s(keys,v)
fmt.Println("Found ... " , n, true)
mv.RUnlock()
}
<-ticker.C
}
}
func main() {
go FetchConfirmedSlots()
go RemoveItemSlotFull()
go GetLatestSlot()
go GetConfirmedBlockHashes()
select {}
}
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
尝试 mv.Lock()
和 mv.Unlock()
,而不是 mv.RLock()
和 mv.RUnlock()
。您正在写信给 confirmed_slot
.
Rlock()
和 RUnlock()
用于读取 - 它们允许多个线程同时读取,只要 none 正在写入。
Lock()
和 Unlock()
将确保一次只有一个线程持有锁,无论它是读还是写。