golang sync.Wait()不执行解决

Golang的sync.WaitGroup陷阱 sync.WaitGroup是并发环境中,一个相当常用的数据结构,用来等待所有协程的结束,在写代码的时候都是按着例子的样子写的,也没用深究过它的使用。前几日想着能不能在协程中执行Add()函数,答案是不能,这里介绍下。 陷阱在WaitGroup的3个函数的调用顺序上。先回顾下3个函数的功能: Add(delta int):给计数器增加delta,比如启动1个协程就增加1。 Done():协程退出... 阅读详情

goroutine 似乎不用解释太多,可以利用它实现多线程,也可以利用它来实现异步事件。
在使用关键字go的过程中,常常会将用到sync.WaitGroup, 如下一段代码。

package main

import (
	"fmt"
	"sync"
	"time"
)

func Run() {
	var wg = &sync.WaitGroup{}
	go func() {
		wg.Add(1)
		fmt.Println("halo world start")
		time.Sleep(time.Second * 5)
		fmt.Println("halo world end")
		wg.Done()
	}()
	// time.Sleep(time.Millisecond * 5)
	// fmt.Println("server will start")
	wg.Wait()
}

func main() {
	Run()
}

// output:
// 

期待的结果是打印 halo world start,5秒后打印halo world end,但是结果就是什么都没有,并且进程立即就结束了。

原因

关键字go是异步的,当执行到go,不会立即执行go 后面的内容,而且继续往下执行。此时wg.Add(1)还没有来得及执行,wg.Wait()就已经执行,即不会发生等待,进程就结束了。

怎么解决:

只需要在wg.Wait()前有其他操作,给与足够的时间让wg.Add(1)执行即可,
方法一、时间等待,在wg.Wait()前加一句time.Sleep(time.Millisecond*5),既不影响性能,也能让wg.Add(1)来得及执行

方法二、有IO操作,在wg.Wait()有其他IO操作,比如fmt.Println("server will start"),原因是std的输出会将进程从用户态转向内核态,打印命令发出后,又切回用户态,这个状态的转换是很有消耗的,wg.Add(1)也就有时间执行。

Don’t worry

是否有存在担心,方法一的时间等待,等待的时候不够长,还是让wg.Add(1)来不及执行。don’t worry.
这里涉及到goroutine的调度问题,go进程在执行过程中,必须从goroutine队列中取出一个来执行,当wg.Wait()执行前就算执行time.Sleep(time.Nanosecond), 一纳秒,一…一…一纳秒,wg.Add(1)也来得及执行,因为主goroutine会被切换到睡眠状态,go进程必须要取一个线程来执行,就会取到wg.Add(1)这个线程,接下来就顺理成章了。

同时方法二也是异曲同工,当发出打印的事件,整个进程都会被切换到就绪态,然后再被cpu执行。

桌面云虚拟机Ubuntu离线安装open-vm-tools 公司办公在桌面云中进行开发,桌面云是无法访问外网的,然后又有安装虚拟机的需求,使用VMware自带的VMware-tools安装功能失败,报错也需要联网才能解决,如果不安装VMware-tools,则虚拟机无法使用共享文件夹功能以及与本机共享剪贴板功能,非常难受,故自己研究解决如何离线安装open-vm-tools(open-vm-tools 是 VMware Tools 的开源实施)打开Ubuntu,可以在文件中看到生成的ISO文件,点开,将四个软件包复制粘贴至桌面。 阅读详情

相关推荐

新手网工别慌!手把手带你搞定华为OLT开局配置(从登录到业务下发全流程)

本文为新手网络工程师提供华为OLT设备开局配置的详细指南,涵盖从设备登录、基础配置到业务部署的全流程。通过实战案例和常见问题排查,帮助读者快速掌握华为OLT配置技巧,确保业务顺利开通。

weixin_33721344的博客 479

深入理解 go sync.Waitgroup

WaitGroup使用了信号量来实现了并发资源控制,sema字段表示信号量。使用会使得 goroutine 阻塞直到计数器减少至0,而使用会使得信号量递增,这等于是通知之前阻塞在信号量上的协程,告诉它们可以继续执行了。WaitGroup作为参数传递的时候,需要传递指针作为参数,否则在被调用函数内对Add或者Done的调用,在caller里面调用的Wait会观测不到。WaitGroup使用一个 64 位的数来保存计数器(高 32 位)和waiter(低 32 位,正在等待的协程的数量)。

SAGGITARXM 685

山景BP10_128DBG开发板通过蓝牙连接手机放歌实验回顾

最近在学习上海山景公司的BP10_128DBG的开发板,因为网上关于BP10开发板的帖子也比较少,在学习的时候也没有太多的参考资料,基本上都是官方的历程。蓝牙放歌这个demo对我来说也比较复杂,特写下此博客进行记录、总结,大家有需要的可以参考。

weixin_56646002的博客 2019

golang学习笔记--WaitGroup

求出n以内的素数并打印出来。

xxzed的博客 350

保姆级教程:用SAP PS管理电梯/大型设备项目(ETO/ATO模式)从成本收集到开票结算

本文详细解析了SAP PS模块在ETO/ATO项目中的全流程成本管理实践,特别针对电梯/大型设备制造行业。从成本收集到开票结算,通过WBS元素、网络活动等核心架构设计,结合F-02、CJ20N等事务代码,实现设计、生产、物流及现场服务各阶段的精准成本控制,助力企业提升项目利润率与财务效率。

weixin_30444105的博客 457

智能车实战——极速越野组GPS与惯导融合定位导航全解析

本文深入解析了智能车极速越野组中GPS与惯导模块的融合定位导航技术。通过对比GPS的全局定位与惯导的高频姿态感知,详细阐述了如何利用MM32SPN27主控,将两者数据融合以实现精准、实时的车辆控制。内容涵盖硬件选型、软件数据处理、PID控制及系统调试等实战环节,为智能车开发者提供了一套完整的解决方案。

pz8901234的博客 1201

go sync wait group deadlock死锁问题

go sync wait group死锁问题,请看下面代码,看起来是没有任何问题的,如果INWait .Add(1)和INWait.Done()都能执行到并且REWait .Add(1)和REWait.Done()也能执行到的情况那肯定是没有问题的. 但是如果在outCh函数中加个return那就出问题了,go run -race xxx.go执行一下,REWait .Add(1)和REWait.Done()不相等,一直阻塞,造成死锁,程序无法退出。 所以开发中waitGroup Add()后立...

或非与博客 1218

Revit Dynamo实战:用Excel数据批量生成桥梁模型(附自适应族技巧)

本文详细介绍了如何利用Revit Dynamo结合Excel数据实现桥梁参数化建模,重点讲解了数据驱动建模、自适应族优化及大型项目性能管理三大核心技巧。通过结构化Excel数据、高级自适应族创建和分块处理策略,显著提升桥梁建模效率与设计变更响应能力。

weixin_42520025的博客 385

go等待一组协程结束的实现方式

waitGroup add():产生每个goroutine时累加器加1。 done():每个goroutine内部的完成销毁时减小计数。 wait():等待所有add的goroutine都执行完,计数为0时触发。 缓存channel 不可保证顺序 非缓存channel 可以保证顺序 package main import ( "fmt" _ "net/http/pprof" "time" ) //var wg sync.WaitGroup var ch = make(chan

m0_37145844的博客 670

双层优化入门(2)—基于yalmip的双层优化求解(附matlab代码)

​上一篇博客介绍了双层优化的基本原理和使用KKT条件求解双层优化的方法,这篇博客将介绍使用yalmip的双层优化问题的求解方法。 1.KKT函数 通过调用yalmip工具箱中的KKT函数,可以直接求出优化问题的KKT条件,省去自己手动写的步骤。 2.solvebilevel函数 solvebilevel是yalmip工具箱内置的求解双层优化问题的函数。也就是通过这个函数,不需要咱手动写KKT条件,也不需要使用KKT函数,直接把上、下层优化的目标函数、约束条件往里面一放,就能求出结果。 ​

配电网和matlab的博客 1万+

RAGFlow核心引擎DeepDoc之PDF解析大起底

本文深入解析RAGFlow中的deepdoc模块,重点介绍了pdf文档解析器的实现细节。deepdoc包含parser(文档解析器)和vision(视觉处理)两大核心功能,其中pdf解析是最复杂的部分。文章详细剖析了PdfParser类的设计架构,包含PlainParser(基础文本提取)、RAGFlowPdfParser(核心处理流水线)和VisionParser(视觉扩展)三个类,它们通过统一的__call__方法返回标准化结果。还具体讲解了初始化过程如何加载OCR引擎、布局识别模型、表格结构识别器等关

yxkong的专栏 2020

go语言WaitGroup 实现原理

提供了一种便捷的机制来等待一组goroutine的完成。它的实现简单而高效,可以应用于各种并发场景。方法会进入一个for循环,不断地检查计数器的值是否为0,如果不是则继续阻塞,如果是则立即返回。是一种并发原语,用于等待一组goroutine的完成。的实现比较简单,它本质上是一个计数器,其初始值为0。方法时,计数器减少1;当计数器的值变为0时,阻塞在。方法内部,使用了一个内置的信号量来实现线程同步。方法上的goroutine将被唤醒。方法时,计数器增加指定数量的值;

abc54250的博客 541

利用GAT(图论分析工具箱)构建并分析大脑结构协变网络学习笔记

前言 前面我学习了利用DTI构建白质纤维脑网络,并采用GRETNA计算了小世界网络属性。阅读文献发现可以利用灰质体积或皮层指标(皮层厚度、折叠指数、沟深)等构建结构协变网络再进行网络拓扑属性的计算。因此,我采用前面提取的灰质体积和皮质数据进行了结构协变网络分析,特此写下笔记以便后面的学习。 一、数据准备 二、构建结构协变网络 三、全局属性的统计分析 四、局部属性的统计分析 五、网络攻击分析 六、度的分布 ..................

weixin_52073820的博客 7496

Go 并发控制--WaitGroup的使用

开发过程中,经常遇到task之间的同步问题。例如,多个子task并发完成一部分任务,主task等待他们最后结束。 在Go语言,实现同步的一种方式就是WaitGroup。 Example package main import ( "fmt" "sync" "time" ) func main() { var wg sync.WaitGroup wg.Add(3) go func(n int){ fmt.Println("n:", n) t := time.Dura

大叶子不小的博客 453

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Go sync.WaitGroup的用法

介绍 经常会看到以下了代码: package main import ( "fmt" "time" ) func main(){ for i := 0; i < 100 ; i++{ go fmt.Println(i) } time.Sleep(time.Second) } 主线程为了等待goroutine都运行完毕,不得不在程序...

稻草人技术博客 2万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Golang sync.WaitGroup 快速上手

sync.WaitGroup 用于阻塞等待一组 Go 程的结束。主 Go 程调用 Add() 来设置等待的 Go 程数,然后该组中的每个 Go 程都需要在运行结束时调用 Done(), 递减 WaitGroup 的 Go 程计数器 counter。当 counter 变为 0 时,主 Go 程被唤醒继续执行。// 设置需要等待的 Go 程数量。// Go 程计数器减 1。// 阻塞等待所有 Go 程结束(等待 Go 程计数器变为 0)。

Doublelv 的博客专栏。 5850

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

golang sync.WaitGroup 用法

执行一个简单协程 package main import ( "fmt" "time" ) func main(){ for i := 0; i < 100 ; i++{ go fmt.Println(i) } time.Sleep(time.Second) } 分析: 为什么会有sleep 呢, 主线程为了等待goroutine...

yangxiaodong88的博客 4065

Golang sync.WaitGroup

Go语言中除了可以使用通道(channel)和互斥锁进行两个并发程序间的同步外,还可以使用等待组进行多个任务的同步,等待组可以保证在并发环境中完成指定数量的任务 在 sync.WaitGroup(等待组)类型中,每个 sync.WaitGroup 值在内部维护着一个计数,此计数的初始默认值为零。 等待组有下面几个方法可用,如下所示。 func (wg *WaitGroup) Add(delta int): 等待组的计数器 +1 func (wg *WaitGroup) Done(): 等待组的计数器 -1

李培冠的博客 1万+

Golang sync.Cond 简介与用法

Cond 实现了一个条件变量,在 Locker 的基础上增加的一个消息通知的功能,保存了一个通知列表,用来唤醒一个或所有因等待条件变量而阻塞的 Go 程,以此来实现多个 Go 程间的同步。 type Cond struct { // L is held while observing or changing the condition L Locker // contains filt...

Doublelv 的博客专栏。 7268

Golang利用sync.WaitGroup实现协程同步详解

###协程同步 在实际项目开发过程中经常会遇到并发需要协程同步的场景,经常看到有人会问如何等待主协程中创建的协程执行完毕之后再结束主协程,例如下面代码,通过起100个协程实现并发打印的例子: package main import ( "fmt" ) func main() { for i := 0; i < 100 ; i++{ go func(i int) { fmt.Println("Goroutine ",i) }(i) } } 执行以上代码很可能看不到输

TigerwolfC的博客 3855

Go语言的sync.Once和sync.Cond

(3)核心变量 notify,阻塞链表,分别存储了调用 Cond.Wait() 方法的次数、goroutine 被唤醒的次数、一把系统运行时的互斥锁以及链表的头尾节点.看下面的代码我们会发现,它有一个解锁的操作,所以在调用他之前,必须是加锁的状态,只有这样才可以执行,然后陷入被动阻塞的状态,阻塞唤醒之后,才会重新加锁。作用:把当前这个持有锁的goroutine,释放锁,陷入一个被动阻塞的状态,加入阻塞队列里面。(2)核心变量 L,一把锁,用于实现阻塞操作;作用:就是唤醒队首的goroutine唤醒。

2303_79710813的博客 1148

GO语言:sync包——WaitGroup_go var wg sync

我们创建并启动两个goroutine,来打印数字和字母,并在main goroutine中,将这两个子goroutine加入到一个WaitGroup中,同时让main goroutine进入Wait(),让两个子goroutine先执行。当两条子goroutine都执行完毕后,WaitGroup中的counter的数值为零,解除main goroutine的阻塞。如果计数器的数值变为0,那么就表示等待时被阻塞的goroutine都被释放,如果计数器的数值为负数,那么就会引发恐慌,程序就报错了。

2401_86449870的博客 514

golang 使用Sync.WaitGroup来解决等待问题

面对goroutine我们都需要等待它完成交给它的事情,等待它计算完成或是执行完毕,所以不得不在程序需要等待的地方使用time.Sleep()来睡眠一段时间,等待其他goroytine执行完毕,下面的代码打印1到100的for循环可以在很快的时间内运行完毕,但是我们必须添加time.Sleep()来等待其打印完毕,如果我们不等待仿佛什么也没有发生一样。。。。。这肯定不是我们想要的! fu...

王佳宇的个人博客 7594

golang sync包条件等待 sync.Cond

本文探讨了Go语言中sync.Cond的使用场景及其与互斥锁的区别。作者通过邮件发送任务的示例,对比了sync.Mutex、chan和sync.WaitGroup的实现方式,指出sync.Cond更适合多个goroutine等待条件满足的场景。sync.Cond通过Wait()挂起程序、Broadcast()/Signal()通知等待者的机制,提供了一种优雅的同步解决方案。文章最后强调sync.Cond本质上仍是基于互斥锁的封装,并指出其通知顺序不确定的特性,建议高层次的同步仍优先使用通道通信。

坚持做正确的事情! 375

Golang sync.Cond详细理解

sync.Cond用于goroutine之间的协作,用于协程的挂起和唤醒。 结构体 type Cond struct { noCopy noCopy // noCopy可以嵌入到结构中,在第一次使用后不可复制,使用go vet作为检测使用 L Locker // 根据需求初始化不同的锁,如*Mutex 和 *RWMutex notify notifyList // 通知列表,...

skh2015java的博客 4065

GoLang之使用sync.Cond

GoLang之使用sync.Cond

weixin_52690231的博客 1958
上一篇: 命令行实现单个进度条,或者刷新一行的内容
下一篇: HashMap实现内存扩容
Tangs_
博客等级 码龄11年 15粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值