goroutine-看一个需求

  • 需求:要求统计 1-9000000000 的数字中,哪些是素数?
  • 分析思路:
  1. 传统的方法,就是使用一个循环,循环的判断各个数是不是素数。[很慢]
  2. 使用并发或者并行的方式,将统计素数的任务分配给多个 goroutine 去完成,这时就会使用到
    goroutine.【速度提高 4 倍】

goroutine-基本介绍

进程和线程介绍

程序、进程和线程的关系示意图

并发和并行

  1. 多线程程序在单核上运行,就是并发
  2. 多线程程序在多核上运行,就是并行
  3. 示意图:
  • 小结

Go 协程和 Go 主线程

Go 主线程(有程序员直接称为线程/也可以理解成进程): 一个 Go 线程上,可以起多个协程,你可以 这样理解,协程是轻量级的线程[编译器做优化]。

Go 协程的特点

  1. 有独立的栈空间
  2. 共享程序堆空间
  3. 调度由用户控制
  4. 协程是轻量级的线程

一个示意图

goroutine-快速入门

案例说明
请编写一个程序,完成如下功能:

  1. 在主线程(可以理解成进程)中,开启一个 goroutine, 该协程每隔 1 秒输出 “hello,world”
  2. 在主线程中也每隔一秒输出"hello,golang", 输出 10 次后,退出程序
  3. 要求主线程和 goroutine 同时执行.
  4. 画出主线程和协程执行流程图

代码实现

输出的效果说明, main 这个主线程和 test 协程同时执行

主线程和协程执行流程图

快速入门小结

  1. 主线程是一个物理线程,直接作用在 cpu 上的。是重量级的,非常耗费 cpu 资源。
  2. 协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。
  3. Golang 的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一 般基于线程的,开启过多的线程,资源耗费大,这里就突显 Golang 在并发上的优势了

goroutine 的调度模型

MPG 模式基本介绍

MPG 模式运行的状态 1

MPG 模式运行的状态 2

设置 Golang 运行的 cpu 数

介绍:为了充分了利用多 cpu 的优势,在 Golang 程序中,设置运行的 cpu 数目

channel(管道)-看个需求

需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到 map 中。最后显示出来。 要求使用 goroutine 完成

分析思路:

  1. 使用 goroutine 来完成,效率高,但是会出现并发/并行安全问题.
  2. 这里就提出了不同 goroutine 如何通信的问题

代码实现

  1. 使用 goroutine 来完成(看看使用 gorotine 并发完成会出现什么问题? 然后我们会去解决)
  2. 在运行某个程序时,如何知道是否存在资源竞争问题。 方法很简单,在编译该程序时,增加一 个参数 -race 即可 [示意图]
  3. 代码实现:
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 之间如何通讯

  1. 全局变量的互斥锁
  2. 使用管道 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(协程)相关推荐

  1. go语言中的goroutine(协程)

    文章目录 goroutine(协程) 1.进程和线程说明: 2.并发和并行说明: 3.go协程和go主线程: 4.MPG 模式基本介绍 5.设置golang运行的cpu数 goroutine(协程) ...

  2. golang实现多协程下载文件(支持断点续传)

    golang实现多协程下载文件(支持断点续传) 引言 写这篇文章主要是周末休息太无聊,看了看别人代码,发现基本上要么是多协程下载文件要么就只有单协程的断点续传,所以就试了试有进度条的多协程下载文件(支 ...

  3. golang goroutine协程运行机制及使用详解

    Go(又称Golang)是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言.Go于2009年正式推出,国内各大互联网公司都有使用,尤其是七牛云,基本都是golang写的, ...

  4. golang goroutine 协程原理

    一.goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字 ...

  5. Go 语言编程 — 并发 — Goroutine 协程

    目录 文章目录 目录 Golang 的协程 go 关键字 Golang 的协程 Golang 的协程被称为 Goroutine.因为操作系统内核是不感知协程的,也就是说 Golang 需要自己实现一个 ...

  6. golang内幕之协程状态切换

    本文承接上一篇文章[golang内幕之程序启动流程][https://blog.csdn.net/QQ1130141391/article/details/96197570] 在 [golang内幕之 ...

  7. go中的goroutine协程

    如下代码: package mainimport ("fmt""time" )//goroutine //python java C++多进程和多线程编程 // ...

  8. golang中通知协程退出的方式

    1 需求分析 go语言中通知子 goroutine 退出的三种方式 方式1 通过全局变量:如果全局变量为真就退出 方式2 通过通道:协程在通道里面取到true就退出 方式3 通过context:通过调 ...

  9. lua学习笔记之协程

    1.基础 所有协程相关的在表coroutine中,创建通过create来创建,参数为函数,返回值类型为thread. 协程状态有:suspended, running, normal, dead.通过 ...

最新文章

  1. 700页的机器学习笔记火了!完整版开放下载
  2. Spring 基于Java配置
  3. [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口
  4. C++静态数据成员和静态成员函数
  5. LeetCode 489. 扫地机器人(DFS)
  6. 蓝牙耳机按键事件linux,调用蓝牙耳机的按键,或者有线耳机的按键方法?
  7. uva11922(强行用rope替代spaly)
  8. 解决“安装程序无法创建新的系统分区,也无法定位现有系统分区”问题方法
  9. utc时间 单位换算_DataTime.Now.Ticks精确的时间单位[转]
  10. NSIS静默安装VC运行库插件
  11. Linux系统平均负载的含义
  12. 史上最简单的word文档docx文档解密方法,忘记word文档docx密码怎么办?
  13. 服务器提取数据库信息,服务器自动提取数据库
  14. 数字信号时序电路_数字电子中的时序电路
  15. sweetjs 简介
  16. 【Mysql SQLZOO练习命令练习】
  17. Windows磁盘管理工具Diskpart之二 管理动态磁盘
  18. Java微信扫码支付
  19. 蛮力法C语言选择排序,2016年法国欧洲杯 -官方网站
  20. uni-app组件封装基本知识

热门文章

  1. Dubbo面试 - dubbo 负载均衡策略和集群容错策略都有哪些?
  2. OpenJDK-11的新特征
  3. Linux——粘滞位(sbit)、sgid、suid 权限
  4. 浅谈CC攻击原理与防范
  5. jquery ajax 设置header的方式
  6. C#开发笔记之10-如何用C#根据发票代码判断发票种类?
  7. python can i use return in wiht statement?
  8. react jest测试_如何设置Jest和Enzyme来测试React Native应用
  9. 泛型 typescript_如何把你的头围绕Typescript泛型
  10. mfc编写鼠标键盘_黑客为什么都不用鼠标?进来你就懂了!