Home > OS >  concurrent map iteration and map write with RLock/RUnlock
concurrent map iteration and map write with RLock/RUnlock

Time:03-05

Not sure why my program is hitting the error of

concurrent map iteration and map write

I have put the RLock()/mv.RUnlock() here

for k := range confirmed_slot {
                keys = append(keys, k)
            }

Here is my complete go program for test

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)
            }


            //sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
            n := sortutil.SearchUint64s(keys,v)
            fmt.Println("Found ... " , n, true)
            mv.RUnlock()
            //if len(keys) > 2 {
            //  if keys[n]-v < v-keys[n-1] {
            //      n  = 1
            //  }
            //  fmt.Printf("%d\n", keys[n-1])
            //}

        }
        <-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)
}

CodePudding user response:

Instead of mv.RLock() and mv.RUnlock() try mv.Lock() and mv.Unlock(). You are writing to the confirmed_slot.

Rlock() and RUnlock() are for reads - they allow many threads to read at once, as long as none are writing.

Lock() and Unlock() will ensure that only one thread holds the lock at a time, regardless of wheather it is reading or writing.

  •  Tags:  
  • go
  • Related