并发不等于并行( Concurrency is not parallelism) —— Rob Pike
Go 语言特别适合编写高并发程序,简单,高效,离不开 Go 语言原生支持的协程(go routine)。
与传统多线程开发不同,Go 语言通过更加轻量级的协程让开发更加便捷,同时避免了许多传统多线程开发需要面对的困难。
Go 语言的并发编程,理解两个内容——协程以及 GMP 模型
协程
在 Go 语言中,协程被认为是轻量级的线程。协程和线程之间通过 Go 语言的调度器关联。协程与线程的关系为 M:N,即多对多。
Go 语言调度器把多个协程调度到一个线程,或者把一个协程调度到多个线程执行。
如果多个协程被分配到不同的线程,这些线程同时被不同的 CPU 核心处理,那么这些协程就是并行处理的。
如果单核执行多个线程,线程之间占用不同的时间片,得到 CPU 的使用权,这些协程就是并发的。
简单协程入门
本节将从一个简单的程序入门,让大家感受一下协程。
有一个程序检查一些网站是否可以访问,构建一个 links 作为 url 列表。
package main
import (
"fmt"
"net/http"
)
//顺序执行
func main() {
links := []string{
"http://www.baidu.com",
"http://www.jd.com/",
"https://www.taobao.com/",
"https://www.163.com/",
"https://www.sohu.com/",
}
for _, link := range links {
checkLink(link)
}
}
func checkLink(link string) {
_, err := http.Get(link)
if err != nil {
fmt.Println(link, "might be down!")
return
}
fmt.Println(link, "is up!")
}
执行结果为:
http://www.baidu.com is up!
http://www.jd.com/ is up!
https://www.taobao.com/ is up!
https://www.163.com/ is up!
https://www.sohu.com/ is up!
当前程序能正常运行,但是有严重的性能问题。网络请求是比较耗时的操作,一个个地检查 url,前一个请求执行完,才轮到后一个请求。
如果其中的几个网站响应慢,整体耗时就很高。这种情况在网络访问,磁盘文件访问时,很常见的场景。
其实 url 之间没有先后的依赖关系,没有规定先检查baidu,再检查 jd。如果能并发检查,就能降低时间。
GMP 模型简介
待续
字节跳动秋招提前批正式开启,所有岗位不设笔试,今年宜早不宜晚
我的内推码: YZSSR9U
投递链接: https://jobs.toutiao.com/s/YEmNcK5
和优秀的人, 做有挑战的事,详情猛戳 -> 字节跳动 2023 校园招聘研发提前批正式启动!