Go 协程基础:轻松入门并发编程,解析 Goroutines 的奥秘

2023-12-10 03:36

本文主要是介绍Go 协程基础:轻松入门并发编程,解析 Goroutines 的奥秘,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、协程基本使用

1、启动一个协程
  • 主线程中每个100毫秒打印一次,总共打印2次
  • 另外开启一个协程,打印10次
  • 情况一:打印是交替,证明是并行的
  • 情况二:开启的协程打印2次,就退出了(因为主线程退出了)
package mainimport ("fmt""time"
)func test() {for i :=o;i<10;i++ {fmt.PrintIn("test() 你好golang")time.Sleep(time.Millisecond * 100)}
}func main() {go test()    //表示开启一个协程for i:=0;i<2;i++ {fmt.PrintIn("main() 你好golang")time.Sleep(time.Millisecond * 100)}
}
/*
main() 你好golang
test() 你好golang
main() 你好golang
test() 你好golang
test() 你好golang
*/
 2、WaitGroup等待协程执行完毕
  • 主线程退出后所有的协程无论有没有执行完毕都会退出
  • 所以我们在主进程中可以通过WaitGroup等待协程执行完毕
    • sync.WaitGroup内部维护者一个计数器,计数器的值可以增加和减少
    • 例如当我们启动了N个并发任务时,就将计数器值增加N
    • 每个任务完成时通过调用Done()方法将计数器减1
    • 通过调用Wait来等待并发任务执行完,当计数器值为0时,表示所有并发任务已经完成

var wg sync.waitGroup      //第一步:定义一个计数器

wg.Add(1)                        //第二步:开启一个协程计数器+1

wg.Done()                        //第三步:协程执行完毕,计数器-1

wg.Wait()                        //第四步:计数器为0时退出

package mainimport ("fmt""sync""time"
)var wg sync.WaitGroup         //第一步:定义一个计数器func  test1() {for i :=0;i<10;i++ {fmt.PrintIn("test1() 你好golang",i)time.Sleep(time.Millisecond * 100)}wg.Done()    //协程计数器-1    //第三步:协程执行玩不,计数器-1
}func  test2() {for i :=0;i<2;i++ {fmt.PrintIn("test2() 你好golang",i)time.Sleep(time.Millisecond * 100)}wg.Done()    //协程计数器-1   
}func main() {wg.Add(1)    //协程计数器+1     第二不:开启一个协程计数器+1go test1()    //表示开启一个协程wg.Add(1)    //协程计数器+1go test2()    //表示开启一个协程wg.Wait()    //等待协程执行完毕... 第四步:计数器为0时退出fmt.PrintIn("主线程退出...")}/*
test2() 你好golang- 0
test1() 你好golang- 0
.....
test1() 你好golang- 8
test1() 你好golang- 9
主线程退出...
*/

 二、多协程案例

1、开启多个协程
  • 在Go语言中实现并发就是这样简单,我们还可以启动多个goroutine
  • 这里使用了sync.WaitGroup来实现等待goroutine执行完毕
  • 多次执行上面的代码,会发现每次打印的数字的顺序都不一致
  • 这是因为10个goroutine是并发执行的,而goroutine的调度是随机的
package mainimport ("fmt""sync"
)var wg sync.WaitGroupfunc hello(i int){defer wg.Done()    //goroutine结束就登记-1fmt.PrintIn("Hello Goroutine!",i)
}func main() {for i :=0;i<10;i++ {wg.Add(1)    //启动一个goroutine就登记+1go hello(i)}wg.Wait()    //等待所有登记的goroutine都结束
}
2、多协程统计素数
  • 需求:要统计1-120000的数字中哪些是素数?goroutine for循环实现
  • 协程 统计 1-30000
  • 协程 统计 30001-60000
  •  协程 统计 60001-90000

  • 协程 统计 90001-120000

  • start:(n-1)*30000+1 end:n*30000

package main
import ("fmt""sync""time"
)
var wg sync.WaitGroupfunc test(n int) {for num := (n-1)*30000 + 1; num < n*30000; num++ {if num > 1 {var flag = truefor i := 2; i < num; i++ {if num%i == 0 {flag = falsebreak}}if flag {fmt.Println(num, "是素数")}}}wg.Done()
}func main() {start := time.Now().Unix()for i := 1; i <= 4; i++ {wg.Add(1)go test(i)}wg.Wait()fmt.Println("执行完毕")end := time.Now().Unix()fmt.Println(end - start) //1毫秒
}

这篇关于Go 协程基础:轻松入门并发编程,解析 Goroutines 的奥秘的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/475916

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署