Don’t communicate by sharing memory; share memory by communicating.
不要通过共享内存来通讯,恰恰相反,要通过通讯来共享内存。
出处:https://blog.golang.org/share-memory-by-communicating
传统的线程模型中,线程之间通信通过共享内存来实现,共享的数据结构需要通过锁来保护,线程访问内存中的数据需要申请锁。
go 语言的并发模型使用goroutines and channels 来实现。通过 channel 来传递数据,并保证在给定时间只有一个 goroutine 能够访问到 channel 中的数据
如何使用 goroutine 和 channel
用户级线程的创建、销毁、调度、状态变更需要我们的程序自己去处理。Go 语言实现了调度 goroutine 的调度器,来帮我们管理用户线程。
这个调度器主要统筹调配 Go 并发模型中的三个主要元素:G(goroutine)、P(processor)、M(machine)
M 是指系统级线程,P 是用来承载多个 G 并且使其适时的与 M 对接的中介。
go 的调度器帮我们做了很多事情。当一个 G 运行在 一个 M 上时,调度器会及时发现其状态变化,比如 G 在等待 I/O 时,调度器就会暂时先将这个 G 从这个 M 上拿开,以释放计算资源供其他正在排队的 G 使用。而当这个 G 需要恢复运行时,调度器又会尽快为其安排计算资源,并恢复其运行。当 M 不够用时,调度器会帮我们向操作系统申请 M,而当某个 M 已经无用时,调度器会帮我们销毁他。
就像线程会有主线程一样,goroutine 也有主 goroutine。主 goroutine 会在 Go 程序的运行准备工作完成后被主动调用。使用 go 携带一个函数,可以启用一个 goroutine ,而主 goroutine 的启动入口函数就是 main。
我理解的 go 关键字:go 关键字会将其后声明的函数注册到 goroutine 等待队列中。然后调度器会为其分配 goroutine 。已存在的 goroutine 会被有限复用,直到没有足够的 goroutine 时,才会去创建新的。
主 goroutine 如果运行完,程序会立即结束。因此有些尚在等待的 goroutine 中的程序可能会无法执行。主 goroutine 也接受调度器的调度,调度器可能会在某个 goroutine 执行到一半时暂停执行,以让所有的 goroutine 都有机会能执行。
所以 goroutine 的运行顺序是不可预知的。
领取专属 10元无门槛券
私享最新 技术干货