控制goroutine 的并发执行数量
goroutine的数量上限是1048575吗?
正常项目,协程数量超过十万就需要引起重视。如果有上百万goroutine,一般是有问题的。
但并不是说协程数量的上限是100多w
1048575的来自类似如下的demo代码:
package main
import (
"fmt"
"math"
"runtime"
"time"
)
// https://zhuanlan.zhihu.com/p/568151296
func main() {
maxCount := math.MaxInt64
for i := 0; i < maxCount; i++ {
go func(i int) {
fmt.Printf("i is: %d,goroutine num: %d\n", i, runtime.NumGoroutine())
// 模拟各种耗时较长的业务逻辑
time.Sleep(10 * time.Second)
}(i)
}
}
执行后,很快报错

panic: too many concurrent operations on a single file or socket (max 1048575)
但这个是因为fmt.Printf导致的:
对单个file/socket的并发操作数超过了系统上限,这个是标准输出造成的,具体一点,就是文件句柄数量达到限制
如下例子,去掉fmt:
package main
import (
"fmt"
"math"
"runtime"
"time"
)
func main() {
maxCount := math.MaxInt64
for i := 0; i < maxCount; i++ {
go func(i int) {
// 模拟各种耗时较长的业务逻辑
//time.Sleep(10 * time.Hour)
time.Sleep(15 * time.Second)
if i > 1300_0000 {
//if runtime.NumGoroutine() > 1000_0000 {
fmt.Println("当前协程数:", runtime.NumGoroutine())
}
}(i)
}
}

实际同一时间可以出现1000w的goroutine,可见goroutine的理论上限绝对不止100w
或者如下:
package main
import (
"fmt"
"math"
"runtime"
"time"
)
func main() {
maxCount := math.MaxInt64
for i := 0; i < maxCount; i++ {
go func(i int) {
// 模拟各种耗时较长的业务逻辑
//time.Sleep(10 * time.Hour)
time.Sleep(15 * time.Second)
//if i > 1300_0000 {
if runtime.NumGoroutine() > 800_0000 {
fmt.Println("当前协程数:", runtime.NumGoroutine())
}
}(i)
}
}

panic: too many concurrent operations on a single file or socket (max 1048575)
goroutine 1231546 [running]:
internal/poll.(*fdMutex).rwlock(0x140000a2060, 0x20?)
/Users/fliter/.g/go/src/internal/poll/fd_mutex.go:147 +0x134
internal/poll.(*FD).writeLock(...)
/Users/fliter/.g/go/src/internal/poll/fd_mutex.go:239
internal/poll.(*FD).Write(0x140000a2060, {0x14635532bc0, 0x19, 0x20})
/Users/fliter/.g/go/src/internal/poll/fd_unix.go:370 +0x48
os.(*File).write(...)
/Users/fliter/.g/go/src/os/file_posix.go:48
os.(*File).Write(0x140000a0008, {0x14635532bc0?, 0x19, 0x10412e25c?})
/Users/fliter/.g/go/src/os/file.go:175 +0x60
fmt.Fprintln({0x104168cf8, 0x140000a0008}, {0x140bde92f88, 0x2, 0x2})
/Users/fliter/.g/go/src/fmt/print.go:285 +0x74
fmt.Println(...)
/Users/fliter/.g/go/src/fmt/print.go:294
main.main.func1(0x0?)
/Users/fliter/go/src/shuang/0000/goNum.go:20 +0x150
created by main.main
/Users/fliter/go/src/shuang/0000/goNum.go:14 +0x54
exit status 2
比较奇怪的是,如果将模拟各种耗时较长的业务逻辑的time.Sleep(15 * time.Second)
改为time.Sleep(10 * time.Hour)
,最终会因为内存过高而signal: killed
。但此时goroutine数量不够多,触发不了if里面的fmt逻辑,故而不会出现panic: too many concurrent operations on a single file or socket (max 1048575)

(而休眠10几s的代码,内存到不了这么大,就已经因为fmt的问题panic了)

控制方式
使用有缓冲的channel,限制并发的协程数量
make(chan struct{}, 300) 创建缓冲区大小为 300 的 channel,在没有被接收的情况下,至多发送 300 个消息则被阻塞。
开启协程前,调用 ch <- struct{}{},若缓存区满,则阻塞。 协程任务结束,调用 <-ch 释放缓冲区。
// 通过channel来控制并发数
package main
import (
"fmt"
"math"
"runtime"
"time"
)
func main() {
ch := make(chan struct{}, 300)
maxCount := math.MaxInt64
for i := 0; i < maxCount; i++ {
ch <- struct{}{}
go func(i int) {
//fmt.Printf("i is: %d,go func num: %d\n", i, runtime.NumGoroutine())
// 模拟各种耗时较长的业务逻辑
//time.Sleep(10 * time.Hour)
time.Sleep(15 * time.Second)
//if i > 1000_0000 {
//if runtime.NumGoroutine() > 1000_0000 {
fmt.Println("当前协程数:", runtime.NumGoroutine())
//}
//读取channel数据
<-ch
}(i)
}
}
当前协程数: 301
当前协程数: 301
当前协程数: 301
当前协程数: 301
当前协程数: 301
当前协程数: 301
当前协程数: 301
当前协程数: 301
当前协程数: 301
...
同时只有301个协程(每15s,处理301个;限制太少,会大大增加程序执行完成需要的时间,具体限制多少,需要权衡,太大太小可能都有问题)
更多参考:
如何控制golang协程的并发数量问题[1]
golang实现并发数控制的方法[2]
golang控制并发数[3]
Golang的并发控制[4]
即所谓的
无缓冲的channel可以当成阻塞锁来使用 (Go用两个协程交替打印100以内的奇偶数)
有缓冲的channel通常可以用来控制goroutine的数量
来,控制一下 goroutine 的并发数量[5]
还有通过协程池,信号量等方式,可参考 【警惕】请勿滥用goroutine[6]
aceld-Go是否可以无限go?如何限定数量?[7]
参考资料
如何控制golang协程的并发数量问题: http://www.manongjc.com/detail/62-ixfkirkdenvuohr.html
[2]golang实现并发数控制的方法: http://www.qb5200.com/article/327027.html
[3]golang控制并发数: https://blog.csdn.net/weixin_38155824/article/details/128240704
[4]Golang的并发控制: https://blog.csdn.net/LINZEYU666/article/details/123020597
[5]来,控制一下 goroutine 的并发数量: https://eddycjy.gitbook.io/golang/di-1-ke-za-tan/control-goroutine
[6]【警惕】请勿滥用goroutine: https://juejin.cn/post/6999807716482875422#heading-5
[7]aceld-Go是否可以无限go?如何限定数量?: https://github.com/catandcoder/golang/blob/main/4%E3%80%81Go%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E6%97%A0%E9%99%90go%EF%BC%9F%E5%A6%82%E4%BD%95%E9%99%90%E5%AE%9A%E6%95%B0%E9%87%8F%EF%BC%9F.md
本文由 mdnice 多平台发布
相关文章:

控制goroutine 的并发执行数量
goroutine的数量上限是1048575吗? 正常项目,协程数量超过十万就需要引起重视。如果有上百万goroutine,一般是有问题的。 但并不是说协程数量的上限是100多w 1048575的来自类似如下的demo代码: package mainimport ( "fmt" "ma…...

深入解析即时通讯App开发中的关键技术
即时通讯App开发在现代社交和通信领域中扮演着重要的角色。随着移动设备的普及和网络的高速发展,人们对即时通讯工具的需求不断增加。本篇文章将深入探讨即时通讯App开发中的关键技术,帮助读者了解该领域的最新动态和技术趋势。 基础架构和通信协议 现…...

ClickHouse进阶(三):ClickHouse 索引
进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容! 🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…...

四、MySQL(表操作)如何添加字段?修改表?删除字段?修改表名?删除表?格式化某张表?
1、添加字段 (1)基础语法: alter table 表名 add 字段名 类型名(长度) [comment注释] [约束]; (2)示例:添加nickname这个字段 2、修改表 修改表中某个字段的【数据类型】/【数据类型&字段名】 &…...

docker启动paddlespeech服务,并使用接口调用
一、检查docker容器是否启动 1.输入命令 systemctl status docker 启动 systemctl start docker 守护进程重启 sudo systemctl daemon-reload 重启docker服务 systemctl restart docker 重启docker服务 sudo service docker restart 关闭docker service docker…...
如何训练ChatGPT以生成音乐和创意艺术作品?
训练ChatGPT生成音乐和创意艺术作品是一个令人兴奋且具有挑战性的任务。这种技术,也被称为生成式艺术,涉及将人工智能(AI)模型与创意艺术的融合。在本文中,我将探讨如何训练ChatGPT以生成音乐和创意艺术作品的过程&…...

北约报告:2023-2043,下一代量子技术的发展与挑战
“当今的新技术正在以令人眼花缭乱的速度发展,我们所有人都可以在负责任且合乎道德的方式开发和部署新技术方面发挥作用。” ——这是副秘书长Mircea Geoană在2023年3月22日、在布鲁塞尔发布《北约科学技术组织2023-2043年趋势报告》时传达的信息。 Geoană先生强调…...

arm版Linux下安装es集群
背景:由于生产上网络没通,没办法,只能自己安装一个es集群的测试环境了,我的电脑是Mac M2,安装的Linux是centos7,也是arm版的。 第一步:查看自己Linux系统的版本 命令:uname -a 例如…...

vConsole调试工具的三种使用方式
1.在html页面时, 在页面引入 cdn 方式引入 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" co…...

不用订阅,不用破解,永久免费使用Axure最新版教程
首先去官网下载最新的axure,你没听错,就是最新的。 下载网址:Axure RP - UX Prototypes, Specifications, and Diagrams in One Tool 下载完后解压安装到本地,并注册属于你自己的账户,开始试用。可惜的是只有30天的试…...

合宙Air724UG LuatOS-Air LVGL API控件--复选框 (Checkbox)
复选框 (Checkbox) 复选框主要是让用户进行一些内容选择,或者同意用户协议。 示例代码 – 复选框回调函数 function event_handler(obj, event) if event lvgl.EVENT_VALUE_CHANGED then print(“State”, lvgl.checkbox_is_checked(obj)) end end – 创建复选框…...

使用nps实现内网穿透
1、介绍 当我们想把内网的一些资源暴露在公网上时,可以使用内网穿透功能。比如公司的内网服务器,部署了平时需要开发的项目,但是回到家中无法访问,就可以使用内网穿透,将公司内网的接口映射到一台公网的服务器上&a…...

时序预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元时间序列预测
时序预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元时间序列预测 目录 时序预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现TCN-BiGRU时间卷积双向门控循环单元时间序列预测&a…...

websocket和uni-app里使用websocket
一、HTTP是无状态协议 特点: 1、浏览器发送请求时,浏览器和服务器会建立一个连接。完成请求和响应。在http1.0之前,每次请求响应完毕后,会立即断开连接。在http1.1之后,当前网页的所有请求响应完毕后,才断…...

Opencv-C++笔记 (18) : 轮廓和凸包
文章目录 一、轮廓findContours发现轮廓drawContours绘制轮廓代码 二.几何及特性概括——凸包(Convex Hull)凸包概念凸包扫描算法介绍——Graham扫描算法 相关API介绍程序示例轮廓集合及特性性概括——轮廓周围绘制矩形框和圆形相关理论介绍轮廓周围绘制矩形 -API绘制步骤程序实…...

【半监督医学图像分割】2022-MedIA-UWI
【半监督医学图像分割】2022-MedIA-UWI 论文题目:Semi-supervise d me dical image segmentation via a triple d-uncertainty guided mean teacher model with contrastive learning 中文题目:基于对比学习的三维不确定性指导平均教师模型的半监督图像分…...
python发送邮件
为了安全起见,我们发送邮件需要使用tls,这样发送的内容都是加密的了,但是该工具批量发送带有自定义内容的邮件不方便,于是写了一个py脚本,使用--data参数,方便批量发送,我们的策略是每天随机发送…...

gitee上传本地项目bug
🤮这个破bug不知道浪费了多长时间,以前没有记录,每次都忘记,这次记下来 问题描述 gitee创建仓库,然后根据它提示的如下命令,但一直报错 原因分析: 把命令复制出来,粘贴到Sublime …...

自然语言处理2-NLP
目录 自然语言处理2-NLP 如何把词转换为向量 如何让向量具有语义信息 在CBOW中 在Skip-gram中 skip-gram比CBOW效果更好 CBOW和Skip-gram的算法实现 Skip-gram的理想实现 Skip-gram的实际实现 自然语言处理2-NLP 在自然语言处理任务中,词向量(…...

穿上App外衣,保持Web灵魂——PWA温故
早在2015年,设计师弗朗西斯贝里曼和Google Chrome的工程师亚历克斯罗素提出“PWA(渐进式网络应用程序)”概念,将网络之长与应用之长相结合,其核心目标就是提升 Web App 的性能,改善 Web App以媲美Native的流…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...