首页 >后端开发 >Golang >并发读写Go结构体时如何防止数据争用?

并发读写Go结构体时如何防止数据争用?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-12-25 04:21:09542浏览

How Can I Prevent Data Races When Concurrently Reading and Writing Go Structs?

在没有显式锁定的情况下并发读写 Go 结构

并发访问 Go 中的共享数据可能是潜在错误的来源,例如数据争用。当对数据结构的访问是并发的,即多个 goroutine 可以同时访问它时,确保数据的读写同步以避免不一致是至关重要的。

结构体的并发访问

考虑以下 Go struct 元数据:

type Metadata struct {
    mu  sync.RWMutex // ?
    key bool
}

正如我们所见,元数据结构体包含一个 bool 类型的字段 key 和另一个sync.RWMutex 类型的字段 mu,它是读写锁的实现。

结构体中的数据争用

如果我们创建一个 Metadata 实例并允许多个 goroutine 同时读写它的字段,我们可能会遇到数据竞争。当多个 Goroutines 并发访问相同的数据并且至少其中一个正在执行写入操作时,就会发生数据竞争。

以下代码演示了在没有显式锁定的情况下对 Metadata 结构体的并发读写访问:

func concurrentStruct() {
    m := new(Metadata)

    for i := 0; i < 100000; i++ {
        go func(metadata *Metadata) {
            for {
                readValue := metadata.key
                if readValue {
                    metadata.key = false
                }
            }
        }(m)

        go func(metadata *Metadata) {
            for {
                metadata.key = true
            }
        }(m)
    }

    select {}
}

在这段代码中,我们创建了一个并发读取和写入关键字段的 goroutine。我们使用 select 语句来阻止主 goroutine,从而允许并发 goroutine 运行。使用 go run -race 命令运行程序,我们会收到一条警告,指出出现了 DATA RACE。

但是,程序继续运行,没有崩溃。这是因为Go运行时有内置的并发检查,但它不能保证安全执行。在这种情况下,数据争用可能会导致未定义的行为和不正确的结果。

解决结构中的数据争用

为了防止并发读取和写入结构时出现数据争用,我们需要使用正确的方法锁定机制。一种方法是使用互斥锁,如以下代码所示:

func concurrentStructWithMuLock() {
    m := new(Metadata)

    go func(metadata *Metadata) {
        for {
            metadata.mu.Lock()
            readValue := metadata.key
            if readValue {
                metadata.key = false
            }
            metadata.mu.Unlock()
        }
    }(m)

    go func(metadata *Metadata) {
        for {
            metadata.mu.Lock()
            metadata.key = true
            metadata.mu.Unlock()
        }
    }(m)

    select {}
}

在此代码中,我们向元数据结构添加了读写锁,并使用 mu.Lock() 和 mu。 Unlock() 同步对关键字段的访问。使用 go run -race 运行程序将不再生成任何警告,表明不存在数据争用。

以上是并发读写Go结构体时如何防止数据争用?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn