登录
首页 >  Golang >  Go问答

使用RLock/RUnlock实现并发地迭代和写入映射

来源:stackoverflow

时间:2024-03-25 13:54:37 204浏览 收藏

在并发环境中,使用 RLock/RUnlock 可以实现对映射的并发迭代和写入。对于只读操作,使用 RLock 可以允许多个线程同时读取映射,而写入操作需要使用 Lock 来确保互斥访问。本文将演示如何使用 RLock/RUnlock 来实现并发地图操作,并提供了一个完整的 Go 程序示例。

问题内容

不确定为什么我的程序会遇到错误

并发地图迭代和地图写入

我已将 rlock()/mv.runlock() 放在这里

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

这是我用于测试的完整 go 程序

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.RLock()mv.RUnlock() 尝试 mv.Lock()mv.Unlock()。您正在写信给 confirmed_slot

Rlock()RUnlock() 用于读取 - 它们允许多个线程同时读取,只要没有线程在写入。

Lock()Unlock() 将确保一次只有一个线程持有锁,无论是读还是写。

以上就是《使用RLock/RUnlock实现并发地迭代和写入映射》的详细内容,更多关于的资料请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>