Go错误集锦 | append操作造成数据竞争
2023-02-26 09:48:39 时间
在Go中,使用append给切片中添加元素是常见的操作。下面我们看一个使用append引起的数据竞争的例子。
在下面的示例中,我们创建一个长度为1的切片,然后通过两个协程使用append往该切片中添加元素,如下:
s := make([]int, 1)
go func() {
s1 := append(s, 1)
fmt.Println(s1)
}()
go func() {
s2 := append(s, 2)
fmt.Println(s2)
}()
在该示例中,会产生数据竞争吗?答案是不会。我们看下为什么。
首先,我们回顾一下slice的基础知识。slice结构的底层是一个数组,另外还有两个属性:长度length和容量cap。长度是指的切片中当前有多少个元素。容量是指底层的数组能容纳的总的元素个数。当使用append操作时,其行为依赖于该slice是否满了,即length是否和cap相等。如果slice已经满了,那么append的操作将会重新分配一个更大空间的新数组,然后将原数组中的元素拷贝过来,再将新元素加在新数组中。如果slice没满,那么append的操作是将新元素直接加到已存在的数组中。
在该示例中,我们创建的切片s的长度和容量都是1,即该切片是满的状态。所以在协程中使用append操作,则各自都会创建一个新的数组,并将新元素添加到自己的新数组中,两个数组空间互不影响。所以不存在是数据竞争的问题。
那如果我们将初始化切片的语句变更成如下这样:
s := make([]int, 0, 1)
同样还是在两个协程中使用append操作给s中添加新的元素,那这样就会导致数据竞争。因为在创建切片s的时候其长度为0,但容量是1,说明该切片是未满的状态,还有空间可以存放数据,所以在协程中使用append进行操作时,实际上是在争抢s[0]的位置。
好了,以上就是今天我们要分享的知识点,希望大家在今后的研发中避免踩同样的坑。
欢迎关注「Go学堂」,让知识活起来
相关文章
- Windows 备份和克隆工具 Macrium Reflect 免费版 8.0.7279 发布
- 利用大数据分析提高客户支持的五种有效方法
- RabbitMQ是如何实现消息路由的?
- w 命令的解释与示例
- 在 Linux 命令行中格式化输出 xml
- 微软 Windows 10 正式版 Build 19045.2486(KB5022282)发布
- 商业智能软件有什么作用?
- 关于 GNU/Linux 操作系统的十个神话
- Oh My Zsh 和 Powerlevel10k:天作之合
- React 的一些优秀安全实践
- Linux 中使用 traceroute 命令跟踪目标地址
- 系统调用导致网络收包卡顿的问题分析
- 谷歌 Chrome 浏览器 109 正式版发布,最后支持 Win7/8.1 的版本
- 高级数据分析常见的五种挑战
- Windows 7 和 Windows 8 停止获取关键安全更新
- EulerMaker:构建 openEuler 全场景生态
- 如何将数据分析带到云端
- 一个项目帮你了解数据集蒸馏Dataset Distillation
- 浅谈软件国产化对数据技术发展的影响
- 谷歌 Chrome 浏览器将支持在特定网站上一键禁用所有扩展