[golang note] 协程基础
协程概念
√ 协程通常称为coroutine,在golang中称为goroutine。
√ 协程本质上是一种用户态线程,它不需要操作系统来进行抢占式调度,在实际实现中寄存在线程之中。
√ 协程系统开销极小,可有效提高单个线程的任务并发性,从而避免使用多线程。而且使用协程编程简单,结构清晰。缺点就是需要编程语言的支持,如果不支持,则需要用户在程序中自行实现调度器。
goroutine
√ goroutine是golang中的轻量级线程实现,由go runtime管理。
• goroutine使用语法
// 定义协程函数
func MyRoutineFunction(参数列表) (返回值列表) {
// 函数体
} // 启动协程
go MyRoutineFunction(参数列表)
√ 启动一个goroutine使用go关键字,go是golang中最重要的关键字,因此这个语言也是以这个关键字命名。
√ 在一个函数前加上go关键字调用,这次调用就会在一个新的goroutine中并发执行,开启goroutine的线程将继续执行。
√ 当被go调用的函数返回时,这个goroutine也自动结束了。如果这个函数有返回值,那么这个返回值会被丢弃。
√ golang程序从main()函数开始执行,当main()函数返回时,程序结束且不等待其他goroutine结束。
• goroutine使用示例
package main import (
"fmt"
"time"
) func Add(x, y int) {
z := x + y
fmt.Println(z)
} func main() {
for i := ; i < ; i++ {
go Add(i, i)
} fmt.Println("main goroutine finished!")
time.Sleep( * time.Second)
}
程序运行两次的结果如下:
可以看出goroutine看上去的确是并发执行,结果具有不确定性。
并发与并行
• 概念
√ 两个队列,一个Coffee机器,那是并发。
√ 两个队列,两个Coffee机器,那是并行。
• golang并发与并行
▶ 并发执行
√ 如果在单核cpu情况下,golang所有的goroutine只能在一个线程里跑 。
√ 如果当前goroutine不发生阻塞,它是不会让出cpu时间给其他goroutine,除非调用runtime.Gosched()主动让出时间片。
√ 如果当前goroutine发生阻塞,它会主动让出cpu时间给其他goroutine执行。
√ golang的runtime包是goroutine的调度器,其中使用runtime.GOMAXPROCS(n)可以控制使用cpu核数。
▪ 例子一
package main import "fmt"
import "time"
import "runtime" func loop() {
fmt.Println("loop starts!")
for i := ; i < ; i++ {
fmt.Printf("%d ", i)
}
fmt.Println()
} func main() {
runtime.GOMAXPROCS(1) // 强制使用1个cpu
go loop()
go loop() time.Sleep( * time.Second)
}
运行结果如下:
▪ 例子二
package main import (
"fmt"
"runtime"
"time"
) func Add(x, y int) {
z := x + y
fmt.Println(z)
} func main() {
runtime.GOMAXPROCS(1) // 强制使用1个cpu
go Add(, )
go Add(, )
go Add(, )
go Add(, )
go Add(, )
go Add(, )
go Add(, )
go Add(, )
go Add(, )
go Add(, ) fmt.Println("main goroutine finished!")
time.Sleep( * time.Second)
}
运行结果如下:
▶ 并行执行
√ 默认情况下,golang是开启多核的,因此一开始的示例中的输出就是无序的。
√ 我们也可以告诉golang我们允许同时最多使用核数。
▪ 例子一
package main import "fmt"
import "time"
import "runtime" func loop() {
fmt.Println("loop starts!")
for i := ; i < ; i++ {
fmt.Printf("%d ", i)
}
fmt.Println()
} func main() {
runtime.GOMAXPROCS() go loop()
go loop()
go loop()
go loop() time.Sleep( * time.Second)
}
多运行几次,可以得到结果:
[golang note] 协程基础的更多相关文章
- [golang note] 协程通信
channel基本语法 • channel介绍 √ golang社区口号:不要通过共享内存来通信,而应该通过通信来共享内存. √ golang提供一种基于消息机制而非共享内存的通信模型.消息机制认为每 ...
- Golang 之协程详解
转自:https://www.cnblogs.com/liang1101/p/7285955.html 一.Golang 线程和协程的区别 备注:需要区分进程.线程(内核级线程).协程(用户级线程)三 ...
- GoLang之协程
GoLang之协程 目前,WebServer几种主流的并发模型: 多线程,每个线程一次处理一个请求,在当前请求处理完成之前不会接收其它请求:但在高并发环境下,多线程的开销比较大: 基于回调的异步IO, ...
- 在C++中使用golang的协程
开源项目cpp_features提供了一个仿golang协程的stackful协程库. 可以在c++中使用golang的协程,大概语法是这样的: #include <iostream> v ...
- pyhon——进程线程、与协程基础概述
一直以来写博客都是实用主义者,只写用法,没信心写原理,但是每一次写作业的过程都有一种掘地三尺的感觉,终于,写博客困难症重症患者经历了漫长的思想斗争,还是决定把从网上淘到的各种杂货和自己的总结放在一起, ...
- Golang 的 协程调度机制 与 GOMAXPROCS 性能调优
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...
- golang:协程安全
多路复用 Go语言中提供了一个关键字select,通过select可以监听channel上的数据流动.select的用法与switch语法类似,由select开始一个新的选择块,每个选择条件由case ...
- Kotlin协程基础
开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 我们已经通过第一个例子学会了启 ...
- Unity协程基础用法
//通过StartCoroutine()开始一个协程//通过StopCoroutine();关闭一个协程//通过StopAllCoroutines()方法来实现关闭所有协程void Start(){D ...
随机推荐
- stylus入门使用方法
https://segmentfault.com/a/1190000002712872
- mysql的引擎myisam和innodb的区别
1. MYISAM和INNODB的不同?答:主要有以下几点区别: a)构造上的区别 MyISAM在磁盘上存储成三个文件,其中.frm文件存储表定义:.MYD (MYData)为数据文件:. ...
- 用cocos2d 2.1制作一个过河小游戏(4): 游戏主逻辑BaseLayer设计
前段时间一直在忙.没有时间更新博客.今天还是抽点时间把最后一小部分游戏的实现放上来吧. BaseLayer.h: #import <GameKit/GameKit.h> #import & ...
- PHP-007(转)
今天安装ecshop的时候最上面出现了一个错误提示:Strict Standards: Only variables should be passed by reference in F:\www.x ...
- Java中自己定义缓存方式
说说自己在开发中经常用到的写法. /** * 数据缓存 * @author * */public class DataCache { /** 对象缓存*/ public static Ma ...
- grep递归查找子目录
想要在各种文件里面找一个指定的文本,本来的方法太土了,在网上搜了一下,发现个好的方法,不过也有些问题.原文如下: 第一个,这个是看别人脚本的,配合find实现,-maxdepth指定深度,如果查找到底 ...
- php学习十一:组合
我们在类当中我往往会用到一些对象,此时的继承就无法满足我们的需求,这个时候我们需要用到组合.继承如果是is..a的关系,那么组合就是has...a的关系,直接在本类里面声明即可,不过声明的是一个对象 ...
- 好用的在线Markdown编辑器
dillinger.io 支持在线编辑,导出为html格式等.
- redis学习之集群报错Node is not empty
遇到的问题及解决办法 在redis.conf里bind 真机ip后,接着重新执行每个redis.conf,最后再创建集群,但报错,如下图所示: 图中报的错即: [ERR] Node 192.168.1 ...
- IOS实例方法和类方法的区别
类方法和实例方法 实例方法是— 类开头是+ 实例方法是用实例对象访问,类方法的对象是类而不是实例,通常创建对象或者工具类. 在实例方法里,根据继承原理发送消息给self和super其实都是发送给s ...