首页  >  文章  >  后端开发  >  Go 中的 Append 与 Goroutine 一起使用时是线程安全的吗?

Go 中的 Append 与 Goroutine 一起使用时是线程安全的吗?

Linda Hamilton
Linda Hamilton原创
2024-11-11 07:53:02489浏览

Is Append in Go Thread-Safe When Used with Goroutines?

Append 真的是线程安全的吗?

在 Go 中处理对共享资源的并发访问时,同步至关重要。常见的做法是使用 goroutine 将元素附加到切片。然而,append 函数本质上并不是线程安全的。

在所描述的情况下,在循环中创建单独的 goroutine 来附加到切片可能会导致数据不一致。这是因为多个 goroutine 同时写入同一切片可能会导致数据竞争。

为了演示这一点,请考虑以下代码片段:

destSlice := make([]myClass, 0)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        destSlice = append(destSlice, tmpObj)
    }(myObject)
}
wg.Wait()

使用 -race 选项运行此代码将揭示多个数据竞赛。为了防止这些竞争,必须采用诸如互斥体之类的同步机制。下面是使用互斥体的修改后的代码片段:

var (
    mu        = &sync.Mutex{}
    destSlice = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        mu.Lock()
        destSlice = append(destSlice, tmpObj)
        mu.Unlock()
    }(myObject)
}
wg.Wait()

另一种解决方案是使用一个通道,goroutine 将要附加的值发送到该通道中。专用的 goroutine 可以处理接收这些值并执行追加操作。

总之,虽然切片元素是不同的变量并且可以在不同步的情况下并发访问,但切片头需要同步以防止并发追加操作期间出现数据争用。

以上是Go 中的 Append 与 Goroutine 一起使用时是线程安全的吗?的详细内容。更多信息请关注PHP中文网其他相关文章!

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