当前位置: 首页 > news >正文

Go——Goroutine介绍

一. 并发介绍

        进程和线程

  • 进程是程序在操作系统中一次执行过程,系统进程资源分配和调度的一个独立单位。
  • 线程是进程执行的实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
  • 一个进程可以创建和撤销多个线程,同一个进程中的多个线程之间可以并发执行。

        并发和并行

  • 多线程程序在一个核CPU上运行,就是并发。
  • 多线程程序在多个核CPU上运行,就是并行。

        协程和线程

  • 协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质有点类似于用户级线程,这些用户级线程的调度也是自己实现的。
  • 线程:一个线程上可以跑多个协程,协程是轻量级线程。

        goroutine只是由官方实现的超级“线程池”。

        每个实际4~5KB的栈内存占用和由于实现机制而大幅减少的创建和销毁开销是go高并发的根本原因。

        并发主要是由切换时间片来实现同时运行,并行则是直接利用多核实现多线程的运行,go可以设置使用核数,以发挥多核计算机的能力。

        goroutine奉行通过通信来共享内存,而不是共享内存来通信。

二. Goroutine

        2.1 介绍

        在java/c++中我们要实现一个并发编程,我们通常需要自己维护一个线程池,并且需要自己取包装一个有一个任务,同时需要自己去调度线程执行任务并维护上下文切换,这一切通常会耗费程序员大量心智。那么能不能有一种机制,程序员只需要定义很多任务,让系统去帮助我们把这些任务分配到CPU上实现并发执行呢?

        Go语言中的goroutine就是这样一种机制,goroutine的概念类似于线程,但goroutine是由Go的运行时(runtime)调度和管理的。Go程序会智能的将goroutine中的任务合理的分配给每一个CPU。Go语言之所以被称为现代化的编程语言,就是因为它在语言层面已经内置了调度核上下文切换的机制。

        在Go语言编程中,你不需要去自己写进程,线程,协程,你的技能包里只有一个技能-goroutine,当你需要让某个任务并发执行的时候,你只需要把这个任务包装成一个函数,开启一个goroutine去执行这个函数就可以了。

  • 使用goroutine

        Go语言中使用goroutine非常简单,只需要在调用函数的时候在前面加上go关键字,就可以为一个函数创建一个goroutine。

        一个goroutine必定对应一个函数,可以创建多个goroutine去执行相同函数。

        2.2 使用

  • 启动单个goroutine

        启动goroutine的方式非常简单,只需要在调用的函数(普通函数和匿名函数)前面加一个go关键字。

        使用协程:

  • 启动多个协程

        我们发现下面的打印不是按顺序打印的,这是因为协程是并发运行的,调度是随机的。

  • 注意:如果主协程退出了,其它子协程会不论在不在运行,会直接退出。

 2.3 goroutine与线程

  • 可增长的栈

        OS线程(操作系统的线程)一般由固定的栈内存(通常2MB),一个goroutine的栈在其生命周期开始只有很小的栈(典型情况下2KB),goroutine的栈不是固定的,它可以按需增大或缩小,goroutine的栈大小限制可以达到1GB,虽然极少会用到这么大。所以在Go语言中一次创建十万左右的goroutine也是可以的。

  • goroutine调度

        GPM是Go语言运行时(runtime)层面的实现,是go语言自己实现的一套调度系统。区别于操作系统调度OS线程。

  • G很好理解,就是个goroutine的,里面除了存放本goroutine信息外,还有与所在P的绑定等信息。
  • P管理着一组goroutine队列,P里面会存储当前goroutine运行的上下文环境(函数指针,堆栈信息及地址边界),P会对自己管理的goroutine队列做一些调度(比如把占用CPU时间较长的goroutine暂停,运行后续的goroutine等)当自己的队列消费完就去全局队列里面取,如果全局队列也消费完了会去其它P的队列里抢任务。
  • M(machine)是Go运行时(runtime)对操作系统内核线程的虚拟,M与内核线程一般是一一对应的关系,一个goroutine最终是要放到M上执行的。

        P与M一般也是一一对应。他们的关系:P管理着一组挂载在M上运行。当一个G长久阻塞在一个M上时,runtime会建立一个M,阻塞G所在的P会把其它的G挂载在新的M上,当旧的G阻塞完成或认为其已经死掉,回收旧的M。

        P的个数是通过runtime.GOMAXPROCS设定(最大256),Go1.5版本之后默认为物理线程数。在并发量大的时候会增加一些P和M,但不会太多,切换太频繁的话得不偿失。

        单从线程调度讲,Go语言相比起其它语言的优势在于OS线程是由OS内核调度的,goroutine则是由Go运行时(runtime)自己的调度器调度的,这个调度器使用一个称为m:n调度技术(复用/调度m个goroutine到n个OS线程)。其一大特点是goroutine的调度是在用户态下完成的,不涉及内核态与用户态之间的频繁切换,包括内存的分配与释放,都是在用户态维护着一个大的内存池,不直接调用系统的malloc函数(除非内存池需要改变),成本比调度OS线程低的多。另外一方面充分利用了多核的硬件资源,近似的把若干goroutine均分在物理线程上,再加上本身的goroutine的超轻量,以上种种保证了go调度方面的性能。

  • 总结

Go语言中的操作系统线程与goroutine之间的关系:

  • 一个操作系统线程对应用户态多个goroutine
  • go语言可以同时使用多个操作系统线程
  • goroutine和OS线程是多对多的关系,即m:n 

三.runtime包

  • runtime.Gosched()

        让出CPU时间片,重新等待安排任务。

package mainimport ("fmt""runtime"
)func main() {go func(s string) {for i := 0; i < 2; i++ {fmt.Println(s)}}("world")//主协程for i := 0; i < 2; i++ {runtime.Gosched() //切以下,再次分配任务fmt.Println("hello ")}
}
  • runtime.Goexit()

        退出当前协程。

  • runtime.GOMAXPROCS

        Go运行时的调度器使用GOMAXPROCS参数来确定需要使用多少个OS线程同时执行Go代码。默认值是机器上的CPU核心数。比如在一个8核心的机器上,调度器会把Go代码同时调度到8个OS线程上。(GOMAXPROCS是m:n调度中的n)

        Go语言可以通过runtime.GOMAXPROCS()函数设置当前程序并发时占用的CPU逻辑核心数。

        Go1.5版本之前,默认使用的是单核心执行。Go1.5版本之后,默认使用全部的CPU逻辑核心。

        我们可以通过将任务分配到不同的CPU逻辑核心上实现并行的效果,在这里举个例子:

        下面的例子是,只是用CPU的一个核心,先完成一个任务,再完成一个任务。

        设置逻辑核心为2,此时两个任务并行执行。

 

相关文章:

Go——Goroutine介绍

一. 并发介绍 进程和线程 进程是程序在操作系统中一次执行过程&#xff0c;系统进程资源分配和调度的一个独立单位。线程是进程执行的实体&#xff0c;是CPU调度和分派的基本单位&#xff0c;它是比进程更小的能独立运行的基本单位。一个进程可以创建和撤销多个线程&#xff0c…...

Centos7,部署etcd集群,基于二进制包,https安全通讯

由于etcd集群https通讯&#xff0c;所以需要自建CA数字证书&#xff0c;学习使用https部署etcd集群前&#xff0c;可以先完成一下&#xff0c;基于http通信的etcd集群&#xff1a; 关于CA原理以及工作可以阅读&#xff0c;以下两篇文章&#xff1a; CA工作原理 对称加密与非对…...

设置MariaDB,创建新库,新用户并授权其可以从任何主机登录

OS:CENTOS 7 1、从系统进入MariaDB # mysql -u root -p 这里的root是指MariaDB的管理员用户&#xff0c;和系统的root不搭边&#xff0c;只是同名而已。 2、看下有哪些库、用户 MariaDB [(none)]> show databases; MariaDB [(none)]>select user,host from mysql.us…...

每日一VUE——组件的生命周期

文章目录 VUE组件的生命周期生命周期钩子函数实例创建Teleport VUE组件的生命周期 组件生命周期 组件从创建到挂载、更新、到销毁的一系列过程被称为组件的生命周期。 生命周期函数 在组件的各个生命周期节点执行的函数&#xff0c;为生命周期钩子函数。 生命周期钩子函数…...

Redis中的BigKey

Redis中的BigKey 文章目录 Redis中的BigKey什么是BigKey&#xff1f;BigKey的危害找到Bigkey删除BigKey优化BigKeyBigKey对持久化的影响对AOF日志的影响对AOF重写和RDB的影响 什么是BigKey&#xff1f; 大 key 并不是指 key 的值很大&#xff0c;而是 key 对应的 value 很大。…...

MySQL中的存储过程详解(上篇)

使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法&#xff0c;看完代码自己敲一遍&#xff0c;十分有用 拖动表名到查询文件中就可以直接把名字拉进来中括号&#xff0c;就代表可写可不写 目录 1.认识存储过程 1.1 存储过程的作用 1.2 存储过程简介…...

面试官:说一说CyclicBarrier的妙用!我:这个没用过...

写在开头 面试官&#xff1a;同学&#xff0c;AQS的原理知道吗&#xff1f; 我&#xff1a;学过一点&#xff0c;抽象队列同步器&#xff0c;Java中很多同步工具都是基于它的… 面试官&#xff1a;好的&#xff0c;那其中CyclicBarrier学过吗&#xff1f;讲一讲它的妙用吧 我&…...

MySQL高可用搭建方案MHA

MHA架构介绍 MHA是Master High Availability的缩写&#xff0c;它是目前MySQL高可用方面的一个相对成熟的解决方案&#xff0c;其核心是使用perl语言编写的一组脚本&#xff0c;是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中&am…...

【vue】用vite创建vue项目

前置要求 要有Node.js 1. 用vite创建vue项目 在cmd中&#xff0c;进入一个文件夹 在文件资源管理器上面的文件目录中&#xff0c;输入cmd&#xff0c;回车在cmd中通过cd命令进入对应文件夹 创建项目 npm create vitelatest # 创建项目创建项目过程中的一些选项 Ok to pro…...

内网渗透-内网环境下的横向移动总结

内网环境下的横向移动总结 文章目录 内网环境下的横向移动总结前言横向移动威胁 威胁密码安全 威胁主机安全 威胁信息安全横向移动威胁的特点 利用psexec 利用psexec.exe工具msf中的psexec 利用windows服务 sc命令 1.与靶机建立ipc连接2.拷贝exe到主机系统上3.在靶机上创建一个…...

Linux命令学习—linux 的常用命令

1.1、改变目录 cd 目录的表达方法&#xff1a; /根目录 .当前目录 .. 上一级目录 ~家目录 #cd / 进入到系统根目录 #cd . 进入当前目录 #cd .. 进入当前目录的父目录&#xff0c;返回上层目录 #cd /tmp 进入指定目录/tmp #cd ~ 进入当前用户的家目录 #cd …...

【Git教程】(十)版本库之间的依赖 —— 项目与子模块之间的依赖、与子树之间的依赖 ~

Git教程 版本库之间的依赖 1️⃣ 与子模块之间的依赖2️⃣ 与子树之间的依赖&#x1f33e; 总结 在 Git 中&#xff0c;版本库是发行单位&#xff0c;代表的是一个版本&#xff0c;而分支或标签则只能被创建在版本库这个整体中。如果一个项目中包含了若干个子项目&#xff0c;…...

最新版IntelliJ IDEA 2024.1安装和配置教程 详细图文解说版安装教程

IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版 文章目录 IntelliJ IDEA 2024.1 最新版如何快速入门体验?IntelliJ IDEA 2024.1 安装和配置教程 图文解说版前言 第一步&#xff1a; IntelliJ IDEA 2024.1安装教程第 0 步&…...

JVM常用参数一

jvm启动参数 JVM&#xff08;Java虚拟机&#xff09;的启动参数是在启动JVM时可以设置的一些命令行参数。这些参数用于指定JVM的运行环境、内存分配、垃圾回收器以及其他选项。以下是一些常见的JVM启动参数&#xff1a; -Xms&#xff1a;设置JVM的初始堆大小。 -Xmx&#xff1…...

分布式锁-redission可重入锁原理

5.3 分布式锁-redission可重入锁原理 在Lock锁中&#xff0c;他是借助于底层的一个voaltile的一个state变量来记录重入的状态的&#xff0c;比如当前没有人持有这把锁&#xff0c;那么state0&#xff0c;假如有人持有这把锁&#xff0c;那么state1&#xff0c;如果持有这把锁的…...

Android Gradle开发与应用 (八) :Kotlin DSL

1. 前言 本文介绍了Gradle Kotlin DSL相关的一些知识点 2. DSL是什么 DSL是为特定领域设计的专门的语言&#xff0c;也就是设计了一门语言&#xff0c;然后解决某个特定的领域的特定问题。 2.1 举例说明 以下的这些都可以称之为DSL 正则表达式 :用于文本处理的特定语言SQ…...

phpstorm 快捷键

PHPstorm最常用的快捷键&#xff0c;提高开发效率 - 知乎 (zhihu.com) 四年精华PHP技术文章整理合集——PHP框架篇 (qq.com) 四年精华PHP技术文合集——微服务架构篇 (qq.com) Vue3 打印票据 预览的库&#xff1a;vue3打印解决方案&#xff1a;Vue-Plugin-HiPrint - 掘金 (j…...

浦大喜奔APP8.0智能升级,发力数字金融深化五大金融篇章服务

1. 浦大喜奔立足科技赋能持续迭代升级&#xff0c;筑牢用户体验护城河 浦发信用卡中心坚持数字科技与客户体验双轮驱动&#xff0c;以科技赋能发展&#xff0c;优化整体系统性能&#xff0c;全方位支撑浦大喜奔 APP提高线上客户服务能力与体验&#xff0c;积极服务民生消费&a…...

自然语言处理、大语言模型相关名词整理

自然语言处理相关名词整理 零样本学习&#xff08;zero-shot learning&#xff09;词嵌入&#xff08;Embedding&#xff09;为什么 Embedding 搜索比基于词频搜索效果好&#xff1f; Word2VecTransformer检索增强生成&#xff08;RAG&#xff09;幻觉采样温度Top-kTop-p奖励模…...

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑&#xff0c;这些问题可能会影响我们的开发效率和代码质量&#xff0c;因此我们需要不断总结和学习&#xff0c;以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结&#xff0c;以提高大家的开发质量。本系列文章…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

DeepSeek越强,Kimi越慌?

被DeepSeek吊打的Kimi&#xff0c;还有多少人在用&#xff1f; 去年&#xff0c;月之暗面创始人杨植麟别提有多风光了。90后清华学霸&#xff0c;国产大模型六小虎之一&#xff0c;手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水&#xff0c;单月光是投流就花费2个亿。 疯…...

结构化文件管理实战:实现目录自动创建与归类

手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题&#xff0c;进而引发后续程序异常。使用工具进行标准化操作&#xff0c;能有效降低出错概率。 需要快速整理大量文件的技术用户而言&#xff0c;这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB&#xff0c;…...