并发地图迭代和地图写入 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() 将确保一次只有一个线程持有锁,无论它是读还是写。