php中文网

如何使用 Golang 函数安全并发遍历数据结构?

php中文网

要安全地并发遍历数据结构,可以使用 golang 的 sync.mutex 或 sync.rwmutex 来锁定数据结构,防止并发访问。其中,sync.mutex 一次仅允许一个 goroutine 访问,而 sync.rwmutex 允许多个 goroutine 并发读取,但仅允许一个 goroutine 写入。

使用 Golang 函数并发安全地遍历数据结构

Golang 提供了一个 sync 包,包含用于实现并发安全的并发原语,可帮助你安全地并发遍历数据结构。

Goroutine

立即学习“go语言免费学习笔记(深入)”;

Goroutine 是一个并发执行的函数。要使用 Goroutine 安全地遍历数据结构,可以使用 sync.Mutex 或 sync.RWMutex 来锁定数据结构,防止并发访问。

sync.Mutex

sync.Mutex 是一个互斥锁,一次只允许一个 Goroutine 访问数据结构:

package main

import (
    "fmt"
    "sync"
)

type ConcurrentMap struct {
    m sync.Mutex
    data map[int]string
}

func (cm *ConcurrentMap) Get(key int) (string, bool) {
    cm.m.Lock()
    defer cm.m.Unlock()
    value, ok := cm.data[key]
    return value, ok
}

func main() {
    cm := &ConcurrentMap{
        data: map[int]string{
            1: "a",
            2: "b",
        },
    }

    ch := make(chan string)

    for i := 1; i <= 10; i++ {
        go func(i int) {
            value, ok := cm.Get(i)
            if ok {
                ch <- fmt.Sprintf("key %d: %s", i, value)
            }
        }(i)
    }

    for i := 0; i < 10; i++ {
        fmt.Println(<-ch)
    }
}

sync.RWMutex

sync.RWMutex 是一个读写锁,允许多个 Goroutine 并发读取数据结构,但一次只允许一个 Goroutine 写入:

package main

import (
    "fmt"
    "sync"
)

type ConcurrentMap struct {
    m sync.RWMutex
    data map[int]string
}

func (cm *ConcurrentMap) Get(key int) (string, bool) {
    cm.m.RLock()
    defer cm.m.RUnlock()
    value, ok := cm.data[key]
    return value, ok
}

func (cm *ConcurrentMap) Set(key int, value string) {
    cm.m.Lock()
    defer cm.m.Unlock()
    cm.data[key] = value
}

func main() {
    cm := &ConcurrentMap{
        data: map[int]string{
            1: "a",
            2: "b",
        },
    }

    ch := make(chan string)

    for i := 1; i <= 10; i++ {
        go func(i int) {
            value, ok := cm.Get(i)
            if ok {
                ch <- fmt.Sprintf("key %d: %s", i, value)
            }
        }(i)
    }

    for i := 0; i < 10; i++ {
        cm.Set(i+10, fmt.Sprintf("new value %d", i+10))
    }

    for i := 0; i < 10; i++ {
        fmt.Println(<-ch)
    }
}

以上就是如何使用 Golang 函数安全并发遍历数据结构?的详细内容,更多请关注php中文网其它相关文章!