首页 > 编程语言 >Go语言并发编程-cnblog

Go语言并发编程-cnblog

时间:2023-05-16 15:55:45浏览次数:32  
标签:协程 语言 并发 缓冲 编程 快递 Go cnblog

并发编程

并发 vs 并行

image-20230516153920360

举个形象点的例子

  • 并发可以理解为一边吃饭,一边喝水,因为人只有一个嘴一个咽喉,所以同一时刻饭和水只能有一样进入,二者只能交替进行
  • 并行可以理解为一边走路一边吃东西,因为走路是靠腿脚,吃东西是靠嘴,二者不相干,相当于两个独立的线程,因而可以同时进行

Go语言实现了并发性能提高的调度模型,通过高效的调度,可以充分发挥多核优势,高效运行,可以说Go语言就是为并发而生的

Goroutine

Go语言中实现高并发有一个重要概念叫协程

image-20230516153944087

  • 线程属于内核态,它的创建、切换、停止都属于很重的系统操作,比较消耗资源,消耗在MB级别
  • 协程属于用户态,可以理解为轻量级的线程,协程的创建和切换由Go语言本身去完成,比线程消耗资源要少很多,消耗在KB级别

快速打印goroutine 0~4

image-20230516154134546

这里我们可以通过在调用的函数前加上 go 关键字来开启一个协程来运行,
在主函数最后加上了一个 time.Sleep 函数用来保证子协程运行结束前 主线程不退出

最终输出

image-20230516154150653

可以看到是乱序的,也就是说goroutine 0~4是通过并行进行输出的

CSP(Communicating Sequential Processes)

说完协程,再来说说协程之间的通信

image-20230516154227034
Go语言是提倡通过通信共享内存而不是通过共享内存而实现通信

  • 像左图通过channel将协程进行连接,就像是传输队列,遵循先入先出,能保证收发的顺序
  • 而像右图通过共享内存实现通信,需要通过互斥量对内存进行加锁,也就是需要获取临界区的权限,这样在一定程度上会影响程序的性能。(基本上只要需要去获取锁,都会多少影响到性能)

所以通过以上两种方式,GO语言为了保证性能,选择了通过通信实现共享内存

Channel

Channel是一种引用类型,它的创建需要使用 make 关键字

image-20230516154257410
Channel又分为无缓冲通道和有缓冲通道

  • 无缓冲通道就像是快递员送快递到楼下,打电话叫我们来拿快递,过程是同步进行的,不见不散。但这样快递员必须等我们下楼拿完快递才会去送出下一份快递,等所有人来拿完才能完成工作
  • 有缓冲通道可以理解为快递员将快递放到驿站,然后通知我们来拿,这样过程就是异步进行的了,快递员在通知完所有人来拿快递后工作就结束了,至于我们什么时候来拿就影响不到他了,效率明显提升,而这个驿站就相当于是缓冲通道,当然如果缓冲通道也就是驿站满了,快递员还是要等待驿站的快递被取走才能继续向里面添加新的快递

下面我们定义两个协程

A 子协程发生0~9数字

B 子协程计算输入数字的平方

主协程输出最后的平方数

image-20230516151412031

在这里我们定义的两个通道,dest作为传输最终结果的通道采用了有缓冲通道,因为考虑到主协程作为消费者可能消费速度没有那么快,为避免消息阻塞,因而添加了缓冲

输出结果

image-20230516151440412

并发安全 Lock

现在我们进行一个测试,对变量执行2000次+1操作,5个协程并发执行

首先测试不加锁的情况

image-20230516154423705

可以看到结果并不一定正确(可能会正确,但那是偶然)

image-20230516154446287

此时我们加上锁

image-20230516151526290

可以看到,此时结果就都是正确的了

image.png

至于为什么不加锁会出现这种问题,这算是一种并发安全问题,可能会出现多个协程读取到同一个x值,然后均对其进行+1操作

例如协程1读取到x此时为50,准备将其进行+1操作,使其变为51,但在其写入51值之前,协程2也读取了x的值为50,也对50进行+1操作,这样在协程1执行完写入x=51的操作后,协程2又重复执行了写入x=51的操作。诸如此类的操作便会导致x最终的值可能会低于预期的结果

WaitGroup

前面我们为了保证在协程执行结束前主协程不退出,都采用了调用time.Sleep函数的方法

但我们并不知道子协程执行所需的一个确切时间,因此就无法精确的设定Sleep的时间

为了解决这个问题,Go语言中提供了WaitGroup

image-20230516154543169

当我们启动了n个协程任务,计数器会加上n,每执行完一个协程,计数器会减1,然后调用Wait函数来阻塞,等待其他协程执行完,当计数器为0则表示所有并发任务执行完成


这里我们再回头看之前快速打印goroutine 0~4的例子,我们就可以用计数器来优化了

image-20230516154632845


那么到这里有关Go语言的并发编程问题就结束了

标签:协程,语言,并发,缓冲,编程,快递,Go,cnblog
From: https://www.cnblogs.com/xuanprogram/p/17405874.html

相关文章

  • python3 获取mongodb表中数据的条数
    说明:此处考虑了时区,mongodb默认使用"格林威治时间"1#!/usr/bin/python323importpymongo4importdatetime5importpytz67#统计8"""9/usr/bin/pip3install-Ivpymongo-ihttp://pypi.douban.com/simple/--trusted-hostpypi.douban.com......
  • mongoDB 批量将某个字段值等于另一个字段值
    将update_time字段的值设置为create_time的值:db.collection_name.find().forEach(function(item){db.collection_name.update({_id:item._id,create_time:{$exists:true}},{$set:{update_time:item.create_time}})}......
  • python3 获取mongodb表的索引
    说明:此处脚本考虑到mongodb里面数据存储的时区转换,mongodb里面的数据使用的是"格林威治"时间1#!/usr/bin/python323importpytz4frompymongoimportMongoClient56"""7/usr/bin/pip3install-Ivpytz-ihttp://pypi.douban.com/simple/--trusted-host......
  • js函数式编程: nderscore.js
    nderscore.js是一个JavaScript工具库,它提供了一整套函数式编程的实用功能,弥补了jQuery没有实现的功能,同时又是Backbone必不可少的部分。官方:[url]http://www.bootcss.com/p/underscore/[/url]......
  • 编程找出 1000 以内的所有完数
    一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3.编程找出1000以内的所有完数。perfect_number_list=[]forperfect_numberinrange(2,1000):#找出一个数的所有因子,加入到因数列表里factor_list=[]forfactorinrange(1,perfect_......
  • Google Ajaxslt 使用
    类似插件:jquery.xslt[url]http://hyperthunk.github.io/jquery.xslt/[/url]jqueryxsltplugin:[url]http://www.jongma.org/webtools/jquery/xslt/[/url][url]http://book.51cto.com/art/200805/72637.htm[/url]a.xml<?xmlversion="1.0&quo......
  • shader编程基础:画线
    以sin曲线为例,任何函数曲线画法类似。画线原理虽然十分简单,却是复杂图形曲线绘制的基础。uv和smoothstep等函数不清楚请参考跳转链接:shader编程基础:画圆#defineT.01voidmainImage(outvec4fragColor,invec2fragCoord){ vec2uv=(fragCoord.xy-0.5*iResoluti......
  • 基于FPGA的点阵屏设计,基于Quartus ii开发,Verilog编程语言,也可移植到vivado开发。
    基于FPGA的点阵屏设计,基于Quartusii开发,Verilog编程语言,也可移植到vivado开发。1、可以显示多个汉字2、暂停、启动控制3、左移右移控制4、调速控制。ID:78800675311255672......
  • 电力系统暂态稳定性Matlab编程/ Simulink仿真 单机无穷大系统发生
    电力系统暂态稳定性Matlab编程/Simulink仿真单机无穷大系统发生各类(三相短路,单相接地,两相接地,两相相间短路)等短路故障,各类(单相断线,两相断线,三相断线)等断线故障,暂态稳定仿真分析1.Matlab编程进行数值分析(采用欧拉法Euler,改进欧拉法improveEuler,4阶龙格库塔法Runger-Kutta),计算故障......
  • 电力系统静态稳定性仿真Matlab编程/simulink仿真 1.用Matlab
    电力系统静态稳定性仿真Matlab编程/simulink仿真1.用Matlab编程,把转子运动方程(摇摆方程)在运行点处线性化,采用小信号分析法,对线性化之后状态方程的系数矩阵求解特征值,根轨迹,通过特征值的特点来判断系统稳定性。2.用simulink搭建搭建单机无穷大系统,对其静态稳定性进行仿真分析。YID:......