golang 并发--goroutine(四)

news2024/12/25 6:42:22

golang 语言最大的特点之一就是语法上支持并发,通过简单的语法很容易就能创建一个 go 程,这就使得 golang 天生适合写高并发的程序。这一章节我们就主要介绍 go 程,但是要想完全理解 go 程我们需要深入研究 GPM 模型,关于 GPM 模型网上已经有很多资料了,这里就不过多介绍了,有兴趣的同学可以请教度娘,这一章节还是主要关注应用层面,主要强调在我们写程序时一下需要注意的点并且给出一些代码示例方便我们理解。

通常来说有三种方式实现并发:进程(process),线程(thread),协程(coroutine),前两个:进程和线程是操作系统实现的,协程是由编程语言来实现的,不同语言实现协程的方式不一样,在叫法上也会有一些区别,例如协程在 java 中就叫协程,python 中叫绿色线程(green thread),golang 中叫 go 程(goroutine,因为本文主要是讲解 golang,后续统一用 “go” 程行文)。

进程,线程,go程,是在三个不同粒度实现的并发:

  • 进程

    操作系统实现,拥有独立的内存空间(变量不共享),有进程号数量的限制,由操作系统调度。

  • 线程

    注意这里有两种概念的线程:操作系统线程;CPU 线程。操作系统线程由操作系统实现,是 CPU 执行的最小单元(一核 CPU 同一时刻只能执行一个线程,40 核 CPU 同一时刻能执行 40 个线程),其位于进程之下,一个进程可以有多个线程,但是一个线程只能属于一个进程,多个线程共享进程的内存空间,在操作变量时要考虑安全问题(要加锁防止两个线程同时修改一个变量),线程数受最大线程号限制,由操作系统调度。

  • go 程(协程)

    golang 语言实现,没有数量限制,go程直接共享内存空间,需要考虑并发安全问题,go程的调度时 golang 来完成的,但是同一时刻 CPU 能执行的go程数受线程数限制。

go 程的支持是 golang 的核心优势之一,golang 在语法上支持 go 程(其他语言大都通过第三方现),正是因为有了 go 程,所以 golang 天生适合高并发场景,下面来看一个最简单的 go 程的例子:

package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        fmt.Println("Hello, I am a goroutine.")
    }()
    fmt.Println("Hello, I am the main goroutine.")
    time.Sleep(1 * time.Millisecond)
}

输出:

Hello, I am the main goroutine.
Hello, I am a goroutine.

上面代码最后有个 time.Sleep,这是为了防止主 go 程提前退出,大家可以自己测试把 time.Sleep(1 * time.Millisecond) 注释掉,看看输出结果有什么变化。

另外,从上面代码中我们也可以看出 go 程的另外一个与进程,线程不同的地方,go 程的创建没有返回(创建进程和线程在创建成功后会返回进程号或线程号),这也就意味着 golang 程序父 go 程没有方法去操作其子 go 程(完全没有方法也是不对的,通过 golang 的 channel 和 context 可以间接的实现,这个在后续章节再详细讲解)。

GOMAXPROCS

GOMAXPROCS 是 golang 并发种很重要的一个参数,正确的设置这个值对 go 程序的执行效率有很大的影响。要想理解 GOMAXPROCS 我们首先需要搞懂 GPM 模型,这里我只是简单介绍一下(详细的还是要请教度娘):G 表示的就是 goroutine(go 程);P 表示 processer,这是 golang 抽象处理的一个概念,用于调度 goroutine,每个 processer 都有一个 goroutine 队列,队列中的 goroutine 会顺序执行,如果正在执行的 go 程阻塞,processer 会调度后面的 go 程执行;M 表示操作系统线程,processer 最终会把goroutine 交给 M 来执行(但是注意:P 和 M 并不是一一对应的,当 M 因为 IO 发送阻塞时 P 会寻找其他的 M 处理 goroutine,如果没有空闲 M 则创建一个)。GOMAXPROCS 设置的就是 P 的最大数量,他表示同一时刻的 CPU 运行最大 goroutine 数,这个值默认等于 CPU 线程数(通过 lscpu 命令可查)。

设置 GOMAXPROCS 的方法

  • 通过环境变量
export GOMAXPROCS=8

然后通过下面代码验证:

package main

import (
  "fmt"
  "runtime"
)

func main() {
  fmt.Printf("GOMAXPROCS=%d\n", runtime.GOMAXPROCS(0))
}

输出结果:

GOMAXPROCS=8
  • 通过代码设置
package main

import (
  "fmt"
  "runtime"
)

func main() {
  runtime.GOMAXPROCS(10)
  fmt.Printf("GOMAXPROCS=%d\n", runtime.GOMAXPROCS(0))
}

输出结果:

GOMAXPROCS=10

注意:这里设置和获取 GOMAXPROCS 使用的都是 runtime.GOMAXPROCS 函数,这个函数参数大于 0 时用于设置 GOMAXPROCS,小于等于 0 时用于获取当前的 GOMAXPROCS。

该如何决定 GOMAXPROCS 的大小

我们知道了 GOMAXPROCS 的设置方法,那么到达设为多少合适呢?这要分为两种情况考虑:

  • 程序运行在物理机上;

    这种情况我们需要考虑两种情形:1、程序是 CPU 密集型(又叫计算密接型)的,GOMAXPROCS 采用默认值(等于物理 CPU 的线程数)就行,如果 GOMAXPROCS 设置过大那么势必会导致多个 P 共用一个 CPU 线程,这样就会因为频繁的调度切换浪费 CPU;2、IO 密集型,这种程序的特点:go 程经常会因为 IO 操作被阻塞,如果 GOMAXPROCS 采用默认值会导致大量 CPU 因为等待 IO 而处于空闲状态,这时候我们就可以设置 GOMAXPROCS 大于 CPU 线程数,根据 IO 操作的密集程度甚至可以远大于 CPU 线程数。

    注意:上面设置的方法都是为了 go 程序充分的使用整个物理机的能力,但是如何如果服务器还需要运行其他服务,并且也需要消耗大量 CPU,这时候我们就需要考虑把 GOMAXPROCS 设置的小一些,防止程序突发占用了整个物理机的 CPU.

  • 程序运行在容器里面,并且容器设置了 resouce limit;

    这种情况我们可以采用 uber 提供的 automaxprocs:https://github.com/uber-go/automaxprocs 由程序自动设置。但是对于第三方程序(没有使用 automaxprocs),我们只能通过环境变量的方式来设置 GOMAXPROCS,但是具体设置为多少,这就只能根据具体容器的 resouce limit 是如何设置的来决定了。

总结:这一章节主要介绍了 GOMAXPROCS,也介绍了该如何设置 GOMAXPROCS,但是上面的场景远远不能覆盖现实情况,生产环境种 GOMAXPROCS 的大小需要综合考虑多种情况。希望这篇文档给大家理解 goroutine 带来一些帮助,如果后续遇到 go 程序性能不理想时可以考 GOMAXPROCS 设置的是否合适。



喜欢的朋友记得点赞、收藏、关注哦!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Wireshark协议相关功能:过滤、启用/禁用、导出和统计查看

简述 Wireshark 是一个非常强大的网络分析工具,广泛用于网络故障排查、安全分析、协议分析等任务。在使用 Wireshark 进行网络抓包和协议分析时,掌握一些基本的操作技巧对于提高效率和准确性至关重要。本文将介绍 Wireshark 中如何进行协议相关的操作&a…

渗透Vulnhub-DC-9靶机

本篇文章旨在为网络安全渗透测试行业靶机教学。通过阅读本文,读者将能够对渗透Vulnhub系列DC-6靶机有定的了解 一、信息收集阶段 DC-9靶场信息: DC-9靶场介绍: https://www.vulnhub.com/entry/dc-9,412/ DC-9靶场下载: https://download.vu…

【Linux系列】Shell 命令:`echo ““ > img.sh`及其应用

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

云图库平台(三)——后端用户模块开发

需求分析:对于用户模块而言,通常要实现下列功能: 用户注册:用户输入账号、密码、确认密码进行注册账号用户登录:用户通过输入账号、密码登录注册账号获取当前登录用户信息:即得到当前已登录用户的信息用户…

怎么设置电脑密码?Windows和Mac设置密码的方法

为电脑设置密码是保护个人信息安全的重要措施。无论是Windows系统还是MacOS系统,设置密码的步骤都相对简单,但需要根据不同的操作系统选择不同的方法。 一、Windows系统电脑密码设置 方法一:通过控制面板设置账户密码 点击桌面左下角的“开…

思考: 与人交际

前晚可能是因为我和某个曾经的同学(我认为是朋友,但是它真的很讨厌,现在觉得它在PUA很多人)发生了一件事情,现在没关系了,算是到此结束了,再也不见。 让我看清楚了人和人的交际需要什么&#xf…

突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除

GitLab停止为中国大陆、香港和澳门地区提供服务,要求用户在60天内迁移账号,否则将被删除。这一事件即将引起广泛的关注和讨论。以下是对该事件的扩展信息: 1. 背景介绍:GitLab是一家全球知名的软件开发平台,提供代码托…

vulnhub靶场-matrix-breakout-2-morpheus攻略(截止至获取shell)

扫描出ip为192.168.121.161 访问该ip,发现只是一个静态页面什么也没有 使用dir dirsearch 御剑都只能扫描到/robots.txt /server-status 两个页面,前者提示我们什么也没有,后面两个没有权限访问 扫描端口,存在81端口 访问&#x…

美股开户网:谷歌搜索迎“大动作”:推出AI模式切换选项应对竞争压力

谷歌的AI战略新举措 近日,硅谷权威媒体《The Information》报道了谷歌即将在其搜索引擎中推出一项全新的功能——“切换到AI模式”。这一新功能将为用户提供更加智能、对话式的回答,标志着谷歌对人工智能(AI)领域的进一步布局&am…

如何在window 使用 conda 环境下载大模型

最近开始学习 变形金刚,最大的问题就是 huggingface 无法访问,无论是翻墙还是通过本地镜像网站HF-Mirror,然后再通过git下载都很慢,影响学习进度,后面看了如下文章,Huggingface配置镜像_huggingface镜像-CS…

WebRTC学习二:WebRTC音视频数据采集

系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC 学习一:获取音频和视频设备 第五篇 WebRTC学习二:WebRTC音视频数据采集 文章目录 系列文章…

内部知识库的未来展望:技术融合与用户体验的双重升级

在当今数字化飞速发展的时代,企业内部知识库作为知识管理的关键载体,正站在变革的十字路口,即将迎来技术融合与用户体验双重升级的崭新时代,这一系列变化将深度重塑企业知识管理的格局。 一、技术融合:开启知识管理新…

淘宝详情API接口怎么去使用,调用解析

淘宝开放平台提供了丰富的API接口,帮助开发者快速实现与淘宝的交互。其中,淘宝详情API是用于获取商品详情的重要接口之一。通过调用该接口,开发者可以获取到商品的详细信息,如价格、库存、描述等。本文将详细介绍如何调用淘宝详情…

框架程序设计-简答以及论述

目录 maven的pom作用: Pointcut("execution(*com.example.dome.*.*(……))") 缓存的作用,redis配置过程 Redis配置过程: SpringBoot缓存配置过程: AOP的五种增强注解: 论述题:包结构作用、…

【开源库 | xlsxio】C/C++读写.xlsx文件,xlsxio 在 Linux(Ubuntu18.04)的编译、交叉编译

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 ⏰发布时间⏰: 2024-12-20 …

频繁拿下定点,华玉高性能中间件迈入商业化新阶段

伴随着智能驾驶渗透率的快速增长,中国基础软件市场开始进入黄金窗口期。 近日,华玉通软(下称“华玉”)正式获得某国内头部轨道交通产业集团的智能化中间件平台定点项目。这将是华玉在基础软件领域深耕和商业化发展过程中的又一重…

Mac电脑移动端抓包

*一、相关软件的安装* *1.下载地址* l Fiddler Everywhere 官网:https://www.telerik.com/download/fiddler-everywhere l Charles 官网:https://www.charlesproxy.com/ l Wireshark 官网:https://www.wireshark.org/download.html *…

Spring Boot 动态定时任务管理系统(轻量级实现)

Spring Boot项目中,实现动态增删和启停定时任务的功能对于许多应用场景来说至关重要。虽然Quartz框架是一个广泛使用的解决方案,但其复杂性和重量级特性可能使得项目变得臃肿和难以维护。为了解决这个问题,本项目旨在实现一个轻量级的定时任务…

提高保养效率:4S店预约系统的设计与开发

3.1可行性分析 开发者在进行开发系统之前,都需要进行可行性分析,保证该系统能够被成功开发出来。 3.1.1技术可行性 开发该4S店预约保养系统所采用的技术是vue和MYSQL数据库。计算机专业的学生在学校期间已经比较系统的学习了很多编程方面的知识&#xff…

网络下载ts流媒体

网络下载ts流媒体 查看下载排序合并 很多视频网站,尤其是微信小程序中的长视频无法获取到准确视频地址,只能抓取到.ts片段地址,下载后发现基本都是5~8秒时长。 例如: 我们需要将以上地址片段全部下载后排序后再合成新的长视频。 …