Golang笔记——goroutine(协程)
goroutine-看一个需求
- 需求:要求统计 1-9000000000 的数字中,哪些是素数?
- 分析思路:
- 传统的方法,就是使用一个循环,循环的判断各个数是不是素数。[很慢]
- 使用并发或者并行的方式,将统计素数的任务分配给多个 goroutine 去完成,这时就会使用到
goroutine.【速度提高 4 倍】
goroutine-基本介绍
进程和线程介绍
程序、进程和线程的关系示意图
并发和并行
- 多线程程序在单核上运行,就是并发
- 多线程程序在多核上运行,就是并行
- 示意图:
- 小结
Go 协程和 Go 主线程
Go 主线程(有程序员直接称为线程/也可以理解成进程): 一个 Go 线程上,可以起多个协程,你可以 这样理解,协程是轻量级的线程[编译器做优化]。
Go 协程的特点
- 有独立的栈空间
- 共享程序堆空间
- 调度由用户控制
- 协程是轻量级的线程
一个示意图
goroutine-快速入门
案例说明
请编写一个程序,完成如下功能:
- 在主线程(可以理解成进程)中,开启一个 goroutine, 该协程每隔 1 秒输出 “hello,world”
- 在主线程中也每隔一秒输出"hello,golang", 输出 10 次后,退出程序
- 要求主线程和 goroutine 同时执行.
- 画出主线程和协程执行流程图
代码实现
输出的效果说明, main 这个主线程和 test 协程同时执行
主线程和协程执行流程图
快速入门小结
- 主线程是一个物理线程,直接作用在 cpu 上的。是重量级的,非常耗费 cpu 资源。
- 协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。
- Golang 的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一 般基于线程的,开启过多的线程,资源耗费大,这里就突显 Golang 在并发上的优势了
goroutine 的调度模型
MPG 模式基本介绍
MPG 模式运行的状态 1
MPG 模式运行的状态 2
设置 Golang 运行的 cpu 数
介绍:为了充分了利用多 cpu 的优势,在 Golang 程序中,设置运行的 cpu 数目
channel(管道)-看个需求
需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到 map 中。最后显示出来。 要求使用 goroutine 完成
分析思路:
- 使用 goroutine 来完成,效率高,但是会出现并发/并行安全问题.
- 这里就提出了不同 goroutine 如何通信的问题
代码实现
- 使用 goroutine 来完成(看看使用 gorotine 并发完成会出现什么问题? 然后我们会去解决)
- 在运行某个程序时,如何知道是否存在资源竞争问题。 方法很简单,在编译该程序时,增加一 个参数 -race 即可 [示意图]
- 代码实现:
package main
import ("fmt""time"
)// 需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到 map 中。// 最后显示出来。要求使用 goroutine 完成// 思路// 1. 编写一个函数,来计算各个数的阶乘,并放入到 map 中.// 2. 我们启动的协程多个,统计的将结果放入到 map 中// 3. map 应该做出一个全局的.var (myMap = make(map[int]int, 10)
)// test 函数就是计算 n!, 让将这个结果放入到myMap
func test(n int) {res := 1for i := 1; i <= n; i++ { res *= i}//这里我们将 res 放入到 myMap myMap[n] = res //concurrent map writes?
}func main() {// 我们这里开启多个协程完成这个任务[200 个] for i := 1; i <= 200; i++ {go test(i)}//休眠 10 秒钟【第二个问题 】time.Sleep(time.Second * 10)//这里我们输出结果,变量这个结果 for i, v := range myMap {fmt.Printf("map[%d]=%d\n", i, v)}
}
4) 示意图:
不同 goroutine 之间如何通讯
- 全局变量的互斥锁
- 使用管道 channel 来解决
使用全局变量加锁同步改进程序
- 因为没有对全局变量 m 加锁,因此会出现资源争夺问题,代码会出现错误,提示 concurrent map writes
- 解决方案:加入互斥锁
- 我们的数的阶乘很大,结果会越界,可以将求阶乘改成 sum += uint64(i)
- 代码改进
package main
import ("fmt""time""sync"
)// 需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到 map 中。// 最后显示出来。要求使用 goroutine 完成// 思路// 1. 编写一个函数,来计算各个数的阶乘,并放入到 map 中.// 2. 我们启动的协程多个,统计的将结果放入到 map 中// 3. map 应该做出一个全局的.var (myMap = make(map[int]int, 10)//声明一个全局变量//lock 是一个全局的互斥锁//sync 同步//Mutex 互斥lock sync.Mutex
)// test 函数就是计算 n!, 让将这个结果放入到myMap
func test(n int) {res := 1for i := 1; i <= n; i++ { res *= i}//这里我们将 res 放入到 myMap //枷锁lock.Lock()myMap[n] = res //concurrent map writes?//开锁lock.Unlock()
}func main() {// 我们这里开启多个协程完成这个任务[200 个] for i := 1; i <= 200; i++ {go test(i)}//休眠 10 秒钟【第二个问题 】time.Sleep(time.Second * 10)lock.Lock()//这里我们输出结果,变量这个结果 for i, v := range myMap {fmt.Printf("map[%d]=%d\n", i, v)}lock.Unlock()
}
Golang笔记——goroutine(协程)相关推荐
- go语言中的goroutine(协程)
文章目录 goroutine(协程) 1.进程和线程说明: 2.并发和并行说明: 3.go协程和go主线程: 4.MPG 模式基本介绍 5.设置golang运行的cpu数 goroutine(协程) ...
- golang实现多协程下载文件(支持断点续传)
golang实现多协程下载文件(支持断点续传) 引言 写这篇文章主要是周末休息太无聊,看了看别人代码,发现基本上要么是多协程下载文件要么就只有单协程的断点续传,所以就试了试有进度条的多协程下载文件(支 ...
- golang goroutine协程运行机制及使用详解
Go(又称Golang)是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言.Go于2009年正式推出,国内各大互联网公司都有使用,尤其是七牛云,基本都是golang写的, ...
- golang goroutine 协程原理
一.goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字 ...
- Go 语言编程 — 并发 — Goroutine 协程
目录 文章目录 目录 Golang 的协程 go 关键字 Golang 的协程 Golang 的协程被称为 Goroutine.因为操作系统内核是不感知协程的,也就是说 Golang 需要自己实现一个 ...
- golang内幕之协程状态切换
本文承接上一篇文章[golang内幕之程序启动流程][https://blog.csdn.net/QQ1130141391/article/details/96197570] 在 [golang内幕之 ...
- go中的goroutine协程
如下代码: package mainimport ("fmt""time" )//goroutine //python java C++多进程和多线程编程 // ...
- golang中通知协程退出的方式
1 需求分析 go语言中通知子 goroutine 退出的三种方式 方式1 通过全局变量:如果全局变量为真就退出 方式2 通过通道:协程在通道里面取到true就退出 方式3 通过context:通过调 ...
- lua学习笔记之协程
1.基础 所有协程相关的在表coroutine中,创建通过create来创建,参数为函数,返回值类型为thread. 协程状态有:suspended, running, normal, dead.通过 ...
最新文章
- 700页的机器学习笔记火了!完整版开放下载
- Spring 基于Java配置
- [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口
- C++静态数据成员和静态成员函数
- LeetCode 489. 扫地机器人(DFS)
- 蓝牙耳机按键事件linux,调用蓝牙耳机的按键,或者有线耳机的按键方法?
- uva11922(强行用rope替代spaly)
- 解决“安装程序无法创建新的系统分区,也无法定位现有系统分区”问题方法
- utc时间 单位换算_DataTime.Now.Ticks精确的时间单位[转]
- NSIS静默安装VC运行库插件
- Linux系统平均负载的含义
- 史上最简单的word文档docx文档解密方法,忘记word文档docx密码怎么办?
- 服务器提取数据库信息,服务器自动提取数据库
- 数字信号时序电路_数字电子中的时序电路
- sweetjs 简介
- 【Mysql SQLZOO练习命令练习】
- Windows磁盘管理工具Diskpart之二 管理动态磁盘
- Java微信扫码支付
- 蛮力法C语言选择排序,2016年法国欧洲杯 -官方网站
- uni-app组件封装基本知识
热门文章
- Dubbo面试 - dubbo 负载均衡策略和集群容错策略都有哪些?
- OpenJDK-11的新特征
- Linux——粘滞位(sbit)、sgid、suid 权限
- 浅谈CC攻击原理与防范
- jquery ajax 设置header的方式
- C#开发笔记之10-如何用C#根据发票代码判断发票种类?
- python can i use return in wiht statement?
- react jest测试_如何设置Jest和Enzyme来测试React Native应用
- 泛型 typescript_如何把你的头围绕Typescript泛型
- mfc编写鼠标键盘_黑客为什么都不用鼠标?进来你就懂了!