聊聊Go语言并发之道

news2024/11/24 4:50:39

在这里插入图片描述

写在前面

  2007年,Go语言诞生于Google公司,2009年开源,2012年推出1.0版本,曾两次获得TIOBE年度语言。2012年起,全球大量的开源项目开始使用Go语言开发,目前Go语言已成为云计算领域事实上的标准语言,特别是在容器领域,诞生了一大批优秀的开源软件,如Docker,Kubernetes等。2017年区块链技术在国内大热,区块链两个大的技术平台以以太坊(Ethereum)和超级账本(Hyperledger)子项目Fabric都是基于Go语言构建的。Go语言的应用领域逐渐扩大,目前的区块链、云计算、中间件和服务器编程领域显现出明显的优势。Go语言最先在云计算盛行,随后大量的互联网初创企业将Go语言作为后台主要开发语言。目前,无论互联网公司的独角兽,还是BAT,都已将Go语言作为其技术栈的重要组成部分。市场对Go语言编程人才的需求量也在持续上升。所以今天聊聊Go语言的核心,并发。

什么是并发和并行

  当前环境下,CPU的工艺制程已经实现了7nm商用。可以预测单颗CPU的性能已经很难有指数级的提升,未来多核是主要的发展方向。硬件对软件的影响显而易见,软件的并发和并行也是未来的发展方向。并发和并行是两个不同的概念,应用程序具备好的并发结构,操作系统才能更好地利用硬件并行执行,同时避免阻塞等待,合理的进行调度,提高CPU利用率。

  • 并行意味着程序在任何时刻都是同时运行的,并行就是在任一粒度的时间内部具备同时执行的能力,具有瞬时性,在于执行。
  • 并发意味着程序在单位时间内是同时运行的,并发实在规定时间内多个请求都能得到执行和处理,具有过程性,在于结构。

GoRoutine

  操作系统本身可以进行线程和进程的调度,本身具备并发能力,但进程切换代价过于高昂,进程切换需要保存现场,耗费较多的时间。Go语言的并发思想就是让应用程序在用户层再构建一级调度将并发的粒度进一步降低,以更大限度地提高程序运行的效率呢。
  Go语言的并发执行体称为goroutine,routine的意思就是例程,所以goroutine叫go例程更合理,我还是习惯直接叫goroutine。

Go语言调度模型

  CPU执行指令的速度是非常快的,大部分简单的指令执行仅需三分之一纳秒,即1s可以执行30亿条简单指令,这个速度已经非常快了,CPU慢在对外部数据的读/写上,外部I/O的速度慢和阻塞是导致CPU使用效率不高的最大原因。在真实的系统中,CPU从来不是瓶颈,而是大部分的时间都被浪费了,所以我们需要增加CPU的有效吞吐量,尽可能让每个CPU核心都有事情做,尽可能提高每个CPU做事的效率。
  应用程序的并发模型是多样的,其中最高效的还是协程,Go的并发执行模型就是一种变种的协程模型。

MPG模型

Go语言天生支持并发,MPG模型是go语言的并发模型

在这里插入图片描述

  • G - Goroutine: Go运行时对goroutine的抽象描述,存放兵法执行的代码入口地址、上下文、运行环境、运行栈等执行相关的元信息。
  • M - Machine:OS内核线程,是操作系统层面调度和执行的实体,负责执行。
  • P - Processor:M运行G时所需要的资源,对资源的一种抽象和管理,P不是一段代码实体,而是一个管理的数据结构, P主要降低M管理调度G的复杂性,增加一个间接的控制层数据结构。

Goroutine特点

  • 有独立的栈空间,共享程序堆空间
  • 调度由用户控制,不能保证多个goroutine的执行顺序
  • goroutine是一个轻量级的用户态的轻量级线程
  • goroutine从主线程开启的,是轻量级的线程,是逻辑态,对资源消耗相对小
  • goroutine可以轻松开启上万个线程。其他编程语言的并发机制是一般基于线程的,开启过多的线程,资源耗费大,这里更加可以体现出Go语言在并发上的优势了

Goroutine使用

普通函数启动goroutine

  代码中使用time模块阻塞了主进程,等待所有goroutine执行完毕后再结束程序,但是这样我们并不知道goroutine何时执行完毕,即对时间的把控没有一个参考,在go语言中,sync提供多个Goroutine同步机制,主要通过WaitGroup实现。

package main

import (
	"fmt"
	"time"
)

// 计算1-100的和
func calc() {
	total := 0
	for i := 0; i <= 100; i++ {
		total += i
	}

	fmt.Printf("%v", total)
}

func main() {
	go calc()

	// 阻塞主进程
	time.Sleep(time.Second)
}

WaitGroup

  sync包提供了多个Goroutine同步机制,主要通过WaitGroup实现。下面代码开启5个Goroutine,

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup

// 计算1-100的和
func calc() {
  // wg.Done()方法等价于 wg.Add(-1)
	defer wg.Done()

	total := 0
	for i := 0; i <= 100; i++ {
		total += i
	}

	fmt.Printf("%v\n", total)
}

func main() {

	for i := 0; i < 5; i++ {
    // 每启动一个Goroutine,同时给wg加1
		wg.Add(1)
		go calc()
	}
	
  // 等待所有Goroutine运行完成
	wg.Wait()
}

Chan

  chan是Go语言的一个关键字,是channel的简写,goroutine是Go语言里面的并发执行体,chan是goroutine之间通信和同步的重要组件。然而在Go语言提倡通过通信来共享内存
  通道分为无缓冲通道和有缓冲通道,无缓冲通道的len和cap都为0。无缓冲通道既可以用于通信,也可以用于两个Goroutine之间同步,有缓冲通道主要用于通信。

使用无缓冲通道实现Goroutine之间同步等待:

package main

import "fmt"

// 计算1-100的和
func calc(c chan bool) {
	total := 0
	for i := 0; i <= 100; i++ {
		total += i
	}
  fmt.Printf("%v", total)
  
	c <- true
}

func main() {
  // 声明一个bool类型的无缓冲通道用来同步等待
	c := make(chan bool)
	go calc(c)

	// 同步等待
	<-c
}

总结

  Goroutine的工作方式,就是多个协程在多个线程上切换,既可以用到多核,又可以减少切换开销。不需要研发过度参与,提高代码效率,在研发过程中继续探寻吧。。。

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

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

相关文章

深度学习常见概念字典(感知机、全连接层、激活函数、损失函数、反向传播、过拟合等)

这一章的所有内容均是为了进入深度学习具体的某某网络而准备的&#xff0c;简单但是非常有必要。 1. 神经网络&#xff08;neural networks&#xff09;的基本组成 1.1 神经元&#xff08;neuron&#xff09; 神经元&#xff08;neuron&#xff09; 是神经网络&#xff08;n…

slf4j常用配置文件读取

slf4j常用配置文件读取 log4j2读取配置文件 日志现在一般都是使用slf4j作为接口、底层实现一般是用log4j2或者logback。 我们先看下log4j2是如何读取配置文件的。 implementation org.apache.logging.log4j:log4j-slf4j-impl:2.19.0如果使用gradle的话。上面的代码就会导入sl…

VS coda C++、python运行与Dbug配置

首先新建终端 一次性使用C方法 检查C编译器是否存在 which g可见位置存在于&#xff1a;/usr/bin/g 一次性命令格式&#xff1a; 使用json配置文件 运行C方法&#xff08;推荐&#xff09;&#xff1a; 根据你查找的g的位置来决定 使用配置好的tasks.json&#xff08;C的…

QT入门-UI-信号槽

目录 一、QWidget类&#xff08;重点&#xff09; 二、子组件&#xff08;掌握&#xff09; 三、样式表&#xff08;熟悉&#xff09; 一、什么是信号槽&#xff1f; 二、信号槽的连接方式 2.1 自带信号→自带槽 2.2 自带信号→自定义槽 2.3 自定义信号 三、传参方式 3.1 成员变…

C#语言实例源码系列-伪装文件

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

Redis分布式锁存在的问题

假设有这样一个场景&#xff0c;在一个购票软件上买一张票&#xff0c;但是此时剩余票数只有一张或几张&#xff0c;这个时候有几十个人都在同时使用这个软件购票。在不考虑任何影响下&#xff0c;正常的逻辑是首先判断当前是否还有剩余的票&#xff0c;如果有&#xff0c;那么…

Spring5.3.0源码下载

目录源码下载环境配置import into idea修改配置gradle-wapper.propertiesbuild.gradleSetting Gradlerefresh Gradle写一个小dome源码研究心得源码下载 Spring5.3.0 Download Address 我们只需要下载zip就行了&#xff0c; 如果忘记了这个地址&#xff0c;可以在Spring Offici…

网络技术——网络运维工程师必会的网络知识(3)(详细讲解)

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.网络层协议与应用 1.网络层的功能 2.IP数据包格式 3.广播与…

100天精通Python(数据分析篇)——第70天:Pandas常用排序、排名方法(sort_index、sort_values、rank)

文章目录每篇前言一、按索引排序&#xff1a;sort_index()1. Series类型排序1&#xff09;升序2&#xff09;降序2. DataFrame类型排序1&#xff09;按行索引排序2&#xff09;按列索引排序二、按值排序&#xff1a;sort_values()1. Series类型排序1&#xff09;升序2&#xff…

冻结集合:不可能增删frozenset()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 冻结集合&#xff1a;不可能增删 frozenset() 选择题 对于以下python代码表述错误的一项是? a{1,2} print("【显示】a",a) a.add(3) print("【执行】a.add(3)【显示】a"…

【现代机器人学】学习笔记七:开链动力学(前向动力学Forward dynamics 与逆动力学Inverse dynamics)

这节的内容主要讲述机器人动力学的内容。相对于本书其他部分运动学内容相比&#xff0c;把动力学一下子合成了一章。看完以后有三个感受&#xff1a; 1.本章难度相对其他章节较大&#xff0c;因此需要反复去看&#xff0c;以求对重要内容的眼熟&#xff0c;不求全部记住&#…

Java window多环境配置

目录JDK版本下载配置内容描述创建JAVA_HOME在Path配置版本切换效果JDK版本下载 Java8 Download address 这个是Java8 的下载地址&#xff0c;下载是要登录的&#xff0c;自己花费一点时间去注册。如果想要下载其它版本的JDK&#xff0c;请看下面的图&#xff0c;然后你就可以看…

QT数据库-网络编程-打包

目录 一、讲解之前 二、数据库基本操作 三、模糊查询 二、编程之前 三、通信结构 一、设置应用图标&#xff08;熟悉&#xff09; 二、Debug和Release模式&#xff08;掌握&#xff09; 三、动态链接库&#xff08;掌握&#xff09; 四、打包&#xff08;熟悉&#xff09; 一、…

FastDDS(10)Transport Layer传输层

传输层在DDS实体之间提供通信服务,负责通过物理传输实际发送和接收消息。DDS层将此服务用于用户数据和发现流量通信。然而,DDS层本身是独立于传输的,它定义了一个传输API,可以运行在实现该API的任何传输插件上。这样,它就不局限于特定的传输,应用程序可以选择最适合其需求…

公众号开发(4) —— 使用Senparc.Weixin SDK进行模板消息推送

微信公众号支持推送模板消息给特定用户&#xff0c;只要获取到公众号用户的openid向微信提供的接口发送post请求即可向特定用户推送模板消息&#xff0c;以下记录简单记录使用Senparc.Weixin SDK进行模板消息推送的过程。 1 模板消息建立 在微信公众号测试账号中添加如下消息…

数据结构之排序【冒泡排序和快速排序之一的实现及分析】内含动态演示图

引言&#xff1a; 今天分享一下一点小事迹&#xff0c;自从从学校回到家里&#xff0c;我已经好久没睡上一个好觉了&#xff0c;因为真的冷&#xff0c;莫名被窝总是感觉很冷&#xff0c;然后穿着袜袜的脚也是冰凉&#xff0c;所以每次早晨要起床的时候总是感觉非常的冷&#…

shell基础使用

一、hello world 首先建立一个tmux vim test.sh //再创建一个test.sh文件 进入文件后&#xff0c;创建一个如下命令&#xff0c;指明bash为脚本解释器 #! /bin/bash //相当与c头文件echo "hello world"运行方式 1.作为可执行文件 acs9e0ebfcd82d7:~$ chmod x test.s…

我是如何将2千万StackOverflow问答翻译成中文的?

大家好&#xff01;大家觉得如果需要翻译SO上全部问答可以怎么做呢&#xff1f;我讲讲我是怎么的&#xff0c;大家看看做得怎么样。 自我介绍 我是一名有10年开发经验的老程序员。做过大数据&#xff0c;做过Java程序员&#xff0c;也做过算法工程师&#xff0c;目前是一名大厂…

Spring Security的项目中集成JWT Token令牌安全访问后台API

Spring Security的项目中集成JWT Token令牌安全访问后台API引言JWT 简介jwt token 的适用场景jwt 的结构完整jwtjwt 的使用方式客户端获取jwt令牌访问受保护资源的具体流程Spring Security 安全框架下使用jwt token新建一个spring boot项目加入spring security 和 jwt 相关依赖…

五、传输层(二)UDP

目录 2.1 UDP概述 2.2 UDP的首部格式 2.3 UDP校验 2.1 UDP概述 UDP无须建立连接。因此不会引入建立连接的时延。 UDP为无连接状态。因此当服务器使用UDP时&#xff0c;一般能支持更多的活动客户机。 UDP分组首部仅有8B的开销&#xff0c;而TCP有20B的首部开销。 应用层…