这是我参与「第五届青训营」伴学笔记创作活动的第 4 天
并发程序是指同时执行多个任务的程序,绝大多数的高级语言均支持并发编程,本文将重点学习go语言中的并发运行机制。
基础概念
并发和并行
- 并发:两个或多个事件在同一时间间隔发生,是同一实体上的多个事件(在同一个处理器上“同时”处理多个任务),并发是一种由于切换间隔短而产生的“同时发生”的错觉,实际上并不是同时。
- 并行:两个或多个事件在同一时刻发生,是在不同实体上的多个事件(在不同处理器上同时处理多个任务。
进程和线程
- 进程:程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。
- 线程:进程的一个执行实体,是CPU调度和分派的基本点位,是比进程更下的能独立运行的基本单位。
- 一个进程可以创建和撤销多个线程,同一个进程中的多个线程之间可以并发执行。
协程和线程
- 协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级线程,这些用户级线程的调度也是自己实现的。
- 线程:一个线程上可以跑多个线程,协程是轻量级的线程。
Goroutine
在go语言中,每一个并发的执行单元叫做一个goroutine。goroutine 是一种非常轻量级的实现,可在单个进程里执行成千上万的并发任务,它是Go语言并发设计的核心。 goroutine 其实就相当于线程,但是它比线程更小,十几个 goroutine 可能体现在底层就是五六个线程,而且go语言内部也实现了 goroutine 之间的内存共享。
当一个程序启动时,其主函数在一个单独的goroutine上运行,被称作main goroutine,新的goroutine则用go语句来创建。
//go 关键字放在方法调用前新建一个 goroutine 并执行方法体
go GetThingDone(param1, param2);
//新建一个匿名方法并执行
go func(param1, param2) {
}(val1, val2)
//直接新建一个 goroutine 并在 goroutine 中执行代码块
go {
//do someting...
}
Channel
channel是go语言在语言级别提供的goroutine间的通信方式,可以使用channel在两个或多个goroutine之间传递消息。
channel 是进程内的通信方式,因此通过 channel 传递对象的过程和调用函数时的参数传递行为比较一致,比如也可以传递指针等。channel 是类型相关的,也就是说,一个 channel 只能传递一种类型的值,这个类型需要在声明 channel 时指定。
定义
ch = make(chan int) // unbuffered channel
ch = make(chan int, 0) // unbuffered channel
ch = make(chan int, 3) // buffered channel with capacity 3
使用
ch <- x // a send statement
x = <-ch // a receive expression in an assignment statement
<-ch // a receive statement; result is discarded
总结
go语言的并发编程主要通过goroutine实现,channel提供了goroutine间通信的方式,在程序中应用并发可以充分利用CPU核心的优势,提高程序的执行效率。