`sync.WaitGroup` --指针传递

news/2025/2/8 20:14:52/文章来源:https://www.cnblogs.com/niumachen/p/18705319

在 Go 语言中,sync.WaitGroup 是一个用于等待一组 goroutine 执行完毕的同步原语,它提供了 AddDoneWait 方法来控制和同步 goroutine 的执行。

关于 noCopy 结构和值拷贝的概念,这是 Go 内部实现的细节,主要与 同步原语的并发安全避免数据竞争 相关。

解释:

sync.WaitGroup 是一个结构体类型,并且在 Go 内部,它被设计为不支持值拷贝的类型,具体实现是通过 noCopy 机制来防止它被拷贝。
sync.WaitGroup 实际上内嵌了一个 noCopy 类型的结构体,目的是保证在并发环境下,该对象不能被不安全地拷贝。

noCopy 的作用:

在 Go 中,结构体是通过 值拷贝 来传递的,这意味着如果你将一个结构体作为函数参数,或者通过赋值给其他变量,那么会创建该结构体的一个副本。这在某些情况下可能导致 数据竞争意外的行为,特别是在涉及并发和同步的场景中。

为了避免这种情况,Go 内部使用了 noCopy 结构体来标记某些类型不能被拷贝。当结构体内部含有 noCopy 标记时,它在编译时就会产生错误,防止结构体被拷贝。

为什么 sync.WaitGroup 不支持值拷贝?

sync.WaitGroup 是用来跟踪和同步多个 goroutine 的工作状态的,如果它被拷贝,可能会导致以下问题:

  1. 并发数据竞争:如果 sync.WaitGroup 被拷贝,并且两个 goroutine 同时对两个不同的副本进行操作(比如调用 AddDone),就可能出现数据竞争,导致程序行为不确定。
  2. 不一致的状态WaitGroup 的计数器是一个共享资源,多个副本的存在可能导致它们的计数器不一致,从而无法正确地同步 goroutine。

因此,Go 设计 sync.WaitGroup 时强制要求它只能作为指针传递,确保多个 goroutine 总是操作同一个 WaitGroup 实例,而不是拷贝的副本。

示例:

错误的使用方法(值拷贝)

package mainimport ("fmt""sync"
)func main() {var wg sync.WaitGroupwg.Add(1)// 错误:将 WaitGroup 传递给函数时,使用的是值拷贝go func(wg sync.WaitGroup) {defer wg.Done()  // 这里会发生错误fmt.Println("Goroutine finished")}(wg)wg.Wait()  // 程序不会等到 goroutine 执行完毕
}

这段代码会编译错误,或者在运行时出现不正确的行为,因为 sync.WaitGroup 被值拷贝传递了,导致主 goroutine 和子 goroutine 操作的是不同的 sync.WaitGroup 实例。

正确的使用方法(指针传递)

package mainimport ("fmt""sync"
)func main() {var wg sync.WaitGroupwg.Add(1)// 正确:通过指针传递 WaitGroupgo func(wg *sync.WaitGroup) {defer wg.Done()  // 正确,操作的是同一个 WaitGroupfmt.Println("Goroutine finished")}(&wg)wg.Wait()  // 等待 goroutine 执行完毕
}

在这个例子中,sync.WaitGroup 通过指针传递,这样就保证了 wg 的所有修改都作用于同一个 WaitGroup 实例,从而确保 goroutine 完成后正确地减少计数,主程序可以等待所有 goroutine 完成。

总结:

  • sync.WaitGroup 内部实现了 noCopy 机制,禁止了值拷贝,目的是避免在并发程序中引发数据竞争和不一致的状态。
  • 为了安全使用 sync.WaitGroup,需要通过指针传递它,而不是通过值传递,确保所有 goroutine 操作的是同一个 WaitGroup 实例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/880955.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2.8 系统基本完成

今天将系统进行完善并通过了测试。 部分界面:数据库成功插入:在测试过程中遇到了一个问题:数据库中查到的某些元素无法正确传递(即为null值),在多次检查测试后发现是命名格式问题(我的程序主要是因为名字中带了“_”符号),在传递过程中无法识别,导致值出现错误,这让…

探索5款强大的报表软件:助力企业决策和数据分析

概述: 随着数据分析和决策的重要性不断提升,报表软件已经成为企业管理不可或缺的工具。报表软件能够将复杂的数据转化为直观的图表和报告,帮助管理层做出准确决策。以下是5款功能强大的报表软件,其中包括了山海鲸报表,每款软件都有其独特的优势,适用于不同的使用场景。 1…

1分钟学会DeepSeek本地部署,小白也能搞定!

DeepSeek 是国内顶尖 AI 团队「深度求索」开发的多模态大模型,具备数学推理、代码生成等深度能力,堪称"AI界的六边形战士"。 DeepSeek 身上的标签有很多,其中最具代表性的标签有以下两个:低成本(不挑硬件、开源) 高性能(推理能力极强、回答准确)一、为什么要…

内存占用与监控方式介绍

1.内存占用 神经网络模型常见的内存占用可以分为以下几个部分: 1.1 模型参数内存定义:神经网络的权重和偏置等参数会占用内存。 计算方法:参数总量 = 各层参数数量的总和。 每个参数的大小取决于数据类型(如 float32 为 4 字节,float16 为 2 字节,int8 为 1 字节)。公式…

WebGPU 版 Kokoro:浏览器端零成本使用高质量 TTS;苹果 ELEGNT 台灯机器人:赋予非人形机器人「情感」

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑…

尝试使用阿里云计算巢部署 DeepSeek-R1

记录一下用阿里云计算巢部署 DeepSeek-R1 的经过。进入阿里云计算巢控制台的服务目录,选择 DeepSeek 社区版,点击「开始部署」,选择最便宜的 ECS 实例 GRID 虚拟化4核30G,费用是 1.748/小时。点击「立即创建」,然后控制台会显示正在部署的状态。部署完成后,控制台会显示公…

未来已来:云手机+AI如何重塑Facebook、Google的智能营销生态

未来已来:云手机+AI如何重塑Facebook、Google的智能营销生态 在数字化浪潮奔涌的当下,科技融合正以令人惊叹的速度重塑各个行业,智能营销领域更是首当其冲。云手机与AI自动化工具的深度融合,为Facebook、Google构建的庞大智能营销生态带来了颠覆性的变革,开拓出全新的发展…

Burp Suite 2024激活汉化

转载自https://blog.csdn.net/m0_52985087/article/details/140299827 前言在项目即将上线阶段,迈入生产环境之际,确保其安全性成为我们不可忽视的首要任务。为筑起一道坚不可摧的安全防线,我们借助业界公认的网络安全利器——Burp Suite,我们将展开一场全面的安全测试,旨…

清华权威出品!104页《DeepSeek从入门到精通》免费领,解锁AI时代的核心竞争力!

引言: 在AI技术席卷全球的今天,如何高效驾驭大模型工具已成为个人与企业脱颖而出的关键。清华大学新闻与传播学院新媒体研究中心元宇宙文化实验室余梦珑博士后团队倾力打造的《DeepSeek从入门到精通》电子书重磅发布!全书104页,从基础操作到高阶技巧,手把手教你玩转国产顶…

win11家庭中文版登录应用提示:“为了对电脑进行保护,已经阻止此应用”

1.家庭中文版组策略里面禁用:以管理员批准模式运行所有管理员 win11打不开组策略,需要复制文本内容到记事本,修改为bat后缀执行 @echo off pushd "%~dp0" dir /b c:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum …

4种比常见的线程池和线程同步买票问题

线程池 所谓的线程池:其实就是线程对象的容器。 可以根据需要,在启动时,创建1个或者多个线程对象。 java中有4种比较常见的线程池。 1.固定数量的线程对象。 2.根据需求动态创建线程:动态创建线程:根据需求来创建线程的个数,会自动给我们分配合适的线程个数来完成任务。 3.…