Go语言goroutine

在别的语言里想要在一个程序中实现多任务,如python,python实现多任务可以使用多进程、多线程、携程。但多进程占用资源,多线程无法发挥多核的优势(GIL),python的协程是单线程的,必须等一个任务作出让步,另一个任务才能执行,如果其中一个任务阻塞住,让不出cpu来,那么整个程序都会被阻塞住。

go语言的goroutine(协程)是一个类似于线程的概念,但是它比线程轻量。当开启了多个goroutine后,程序会将每个goroutine分配给每个cpu的核心,可以充分发挥cpu多核的效率。go的协程效率比为m(cpu核数)/n(goroutine数),而python的协程的效率比为1/n

开启goroutine

只需要在将任务封装成一个函数,使用go关键字,就可以开启一个goroutine完成多任务。同时,程序的主函数也是一个goroutine

package main

import "fmt"

func work() {
fmt.Printf("work goroutine")
} func main() {
go work()
fmt.Println("main goroutine")
}

sync.WaitGroup

上面的程序启动goroutine是没问题,但是编译运行后会发现只有打印了main goroutine。这是因为,开启在主goroutine里面启动另外一个goroutine后,另外开启的goroutine还没来得及运行,主goroutine就已经结束了,主goroutine结束,由主goroutine中开启的goroutine全部都会结束,所有主goroutine想要其他的goroutine执行,必须得等待。

package main

import (
"fmt"
"time"
) func work() {
fmt.Println("work")
} func main() {
go work()
fmt.Println("main goroutine")
time.Sleep(time.Second)
}

使用time.Sleep来是程序休眠,来达到让另外goroutine由充足的时间来运行

但是当开启了多个goroutine后,我们不知道全部的协程运行完毕需要多少时间,我们就无法估量sleep的时间。sleep的时间可能多了,可能少了,少了就会让能成达不到想要的目的,多了就会让程序多休眠,浪费资源,此时,就需要引入sync模块的工具来解决这个问题

package main

import (
"fmt"
"sync"
) var wg sync.WaitGroup func work() {
defer wg.Done()
fmt.Println("work") } func main() {
wg.Add(1)
go work()
fmt.Println("main goroutine")
wg.Wait() // 等待所有的协程能全部运行完毕
}

使用sync.WaitGroup,当需要开启一个协程前,往WaitGroup里面加1,在协程结束后,向WaitGroup告知已经完成(可以配合defer 关剪字使用),最后在主goroutine(main函数)的最后使用WaitGroup来等待所有的goroutine运行结束(对应的函数执行结束)

goroutine和线程的关系

这里的线程指的是操作系统的线程,线程和goroutine启动占用的资源不一样,线程的栈内存一般为2mb,而goroutine在开始的时候占用的栈内存为2kb,goroutine的栈不是固定的,它可以像go的切片一样扩容,最大限制可以达到一个G,所有在go里面可以很容易开启十万个goroutine。

  • GMP调度

    • G:G代表goroutine,里面存放当前的goroutine的信息和当前goroutine所载的P的绑定等信息
    • M:M是go运行时对操作系统的线程的虚拟。一个goroutine最终都是要放在M上运行的
    • P:P管理者一组goroutine队列,P里面存放着当前的goroutine的上下文,P会对当前管理的goroutine队列做一些调度(某些goroutine可能占用cpu时间过长,P会将这个goroutine暂停,然后去让别的goroutine来执行)。当自己的goroutine全部运行结束了,这个P会去全局的队列里面取,如果全局的里面也没有了,它甚至会去别的P里面取获取goroutine,这样可以实现效率的最大化
    • P与M一般也是一一对应的。他们关系是: P管理着一组G挂载在M上运行。当一个G长久阻塞在一个M上时,runtime会新建一个M,阻塞G所在的P会把其他的G 挂载在新建的M上。当旧的G阻塞完成或者认为其已经死掉时 回收旧的M。

go语言goroutine的更多相关文章

  1. TODO:Go语言goroutine和channel使用

    TODO:Go语言goroutine和channel使用 goroutine是Go语言中的轻量级线程实现,由Go语言运行时(runtime)管理.使用的时候在函数前面加"go"这个 ...

  2. Go语言goroutine调度器初始化(12)

    本文是<Go语言调度器源代码情景分析>系列的第12篇,也是第二章的第2小节. 本章将以下面这个简单的Hello World程序为例,通过跟踪其从启动到退出这一完整的运行流程来分析Go语言调 ...

  3. Go语言goroutine调度器概述(11)

    本文是<go调度器源代码情景分析>系列的第11篇,也是第二章的第1小节. goroutine简介 goroutine是Go语言实现的用户态线程,主要用来解决操作系统线程太“重”的问题,所谓 ...

  4. Go语言 - goroutine

    并发与并行 并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天). 并行:同一时刻执行多个任务(你和你朋友都在用微信和女朋友聊天). Go语言的并发通过goroutine实现.goroutin ...

  5. Go语言 | goroutine不只有基础的用法,还有这些你不知道的操作

    今天是golang专题第15篇文章,我们来继续聊聊channel的使用. 在我们的上篇文章当中我们简单介绍了golang当中channel的使用方法,channel是golang当中一个非常重要的设计 ...

  6. Go语言学习之8 goroutine详解、定时器与单元测试

    主要内容: 1.Goroutine2. Chanel3. 单元测试 1. Goroutine Go 协程(Goroutine)(轻量级的线程,开线程没有数量限制).   (1)进程和线程 A. 进程是 ...

  7. 09. Go 语言并发

    Go 语言并发 并发指在同一时间内可以执行多个任务.并发编程含义比较广泛,包含多线程编程.多进程编程及分布式程序等.本章讲解的并发含义属于多线程编程. Go 语言通过编译器运行时(runtime),从 ...

  8. 分布式 基本理论 BASE

    比起CAP的生硬来, 我更加喜欢BASE.BASE 显得更加好理解.尽管BASE 这个名字本身有迎合语言习惯的恶臭味,为什么不是缩写为 BaSsEc 呢? 其实大部分系统是可以 同时 CAP 的, 因 ...

  9. golang 学习笔记 ---内存分配与管理

    Go语言——内存管理 参考: 图解 TCMalloc Golang 内存管理 Go 内存管理 问题 内存碎片:避免内存碎片,提高内存利用率. 多线程:稳定性,效率问题. 内存分配   内存划分 are ...

随机推荐

  1. 【翻译】.NET 5 Preview 1 发布

    .NET 5 Preview 1 发布 去年年底,我们发布了.NET Core 3.0和3.1.这些版本添加了桌面应用程序模型Windows Forms(WinForms)和WPF,ASP.NET B ...

  2. vue练手项目——桌面时钟

    用vue实现一个简单的网页桌面时钟,主要包括时钟显示.计时.暂停.重置等几个功能. 效果图如下,页面刚进来的时候是一个时钟,时钟上显示的时.分.秒为当前实际时间,点击计时器按钮后,页面变成一个计时器, ...

  3. jmeter 性能测试基本过程及示例

    jmeter 为性能测试提供了一下特色: jmeter 可以对测试静态资源(例如 js.html 等)以及动态资源(例如 php.jsp.ajax 等等)进行性能测试jmeter 可以挖掘出系统最大能 ...

  4. turtle学习笔记

    1.turtle的绘图窗体 turtle.setup(width, height, startx,starty) - setup()设置窗体大小及位置- 4个参数中后两个可选(后两个省略时默认窗口在屏 ...

  5. (转)协议森林04 地址耗尽危机 (IPv4与IPv6地址)

    协议森林04 地址耗尽危机 (IPv4与IPv6地址) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! IP地址是IP协议的重要组 ...

  6. mysql那些事之索引篇

    mysql那些事之索引篇 上一篇博客已经简单从广的方面介绍了一下mysql整体架构以及物理结构的内容. 本篇博客的内容是mysql的索引,索引无论是在面试还是我们日常工作中都是非常的重要一环. 索引是 ...

  7. JS实现滚动区域触底事件

    效果 贴上效果展示: 实现思路 样式方面不多赘述,滚动区域是给固定高度,设置 overflow-y: auto 来实现. 接下来看看js方面的实现,其实也很简单,触发的条件是: 可视高度 + 滚动距离 ...

  8. javaweb_HTML

    第一章:网页的构成 1.1概念:b/s与c/s 1.1.1 现在的软件开发的整体架构主要分为B/S架构与C/S架构: b/s:浏览器/服务器 c/s:客户端/服务器 客户端:需要安装在系统里,才可使用 ...

  9. Reverse Subarray To Maximize Array Value

    2020-02-03 20:43:46 问题描述: 问题求解: public boolean canTransform(String start, String end) { int n = star ...

  10. 使用Promethus+Grafana监控Mongodb

    note:本人周五开始接触promethuse,周一上班就开始搭环境和配置监控,其实本人对这三个东西根本就是略知一二,但是,我预测感觉过程还是简单的,结果... 首先把过程和遇到的问题一一说明. 1. ...