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执行。

保姆级教程:在iQuant平台从零写一个Python量化策略(附完整代码示例) 本文提供了一份详细的iQuant平台Python量化策略开发教程,从环境准备到策略实现、回测优化,再到实盘运行,每个步骤都配有完整代码示例和常见问题解决方案。适合量化交易新手快速上手,掌握双均线策略等核心开发技巧。 阅读详情

相关推荐

格(Lattice)基础(一)

有关格的基础概念,和相关的格难题

Amire0x的小乐园 5698

深入理解 go sync.Waitgroup

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

SAGGITARXM 685

LabVIEW+数据库应用系列保姆级教程,第一篇数据库连接

目录LabVIEW连接数据库的方法连接MySQL连接Oracle,SQL Server,Access等 LabVIEW连接数据库的方法 1、创建udl(Universal Data Link)是通用数据连接文件。界面操作,简单快捷。 2、编写连接字符串。需要熟悉连接字符串的结构,容易出错。 3、其他… 本教程教你使用第1种方法,也是最简单、最常用的方法。 连接MySQL 1、在MySQL Installer内安装MySQL Connector/ODBC,建议安装32位(X86),如下图: 2、创建ODBC

wwplh5520370的博客 1万+

golang学习笔记--WaitGroup

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

xxzed的博客 350

避坑指南:SpringBoot对接拉卡拉支付常见问题与解决方案(含SDK 1.0.6配置技巧)

本文是一份SpringBoot项目对接拉卡拉支付的实战避坑指南。针对SDK 1.0.6版本,详细剖析了从依赖管理、多环境配置、SDK初始化到支付请求构建、回调验签及生产监控的全流程常见问题,并提供了经过验证的解决方案与配置技巧,旨在帮助开发者高效、稳定地集成支付功能。

k5l6m的博客 330

真格量化-bs套利

#!/usr/bin/env python # coding:utf-8 from PoboAPI import * import datetime import time import numpy as np from copy import * #开始时间,用于初始化一些参数 def OnStart(context) : context.myacc = None #登录交易账号 if context.accounts["回测期权"].Login() : co.

qq_26742269的博客 1319

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

CDR插件开发之CPG插件004 - 认识VGCore并编译生成你的第一个CPG文件

上篇文章中,讲到了使用VS2019编译CDR类型库 VGCoreAuto.tlb,编译后得到了vgcoreauto.tlh和vgcoreauto.tli两个文件。本文将对这两个文件说明,并演示通过标准的libid形式来导入CDR类型库,在这个过程中,穿插一些VS2019的使用技巧(删除目录、复制工程、打开项目或解决方案、修改解决方案名称、修改项目名称等),使读者循序渐进,逐步提高对VS2019工具的熟练程度,最后通过修改项目属性配置,生成第一个CPG文件。

Zebe 2983

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

初探802.11协议(6)——Wi-Fi 6新特性简介

Wi-Fi 6新机制(特性)介绍

FanFF的博客 1522

【点云鸟瞰图BEV】点云鸟瞰图BEV原理与可视化

本节将介绍激光雷达等点云的鸟瞰图生成原理、代码及效果图。 1 BEV视图原理 点云BEV(Bird's Eye View)视图是指点云在垂直于高度方向的平面上的投影。通常,在获得bev视图前,会将空间分割成体素,利用体素对点云进行下采样,然后将每个体素作为一个点进行投影。体素是指将三维空间按照固定尺寸长方体进行划分时的长方体(Δl*Δw*Δh)。 体素投影时可以得到BEV视图的像素点坐标。每个像素点的特征取值则可以通过多种方式得到。 ...

叶子的博客 2万+

go语言WaitGroup 实现原理

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

abc54250的博客 541

12027.linux flash驱动之IS25LP01G/IS25WWP01G

一页:512字节 --> 扇区 4096字节 --> 块 32k,64k, 层层递进关系。

写给自己的笔记 2288

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

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

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万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

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

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

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、付费专栏及课程。

余额充值