Go语言圣经 .8.使用共享变量实现并发

使用共享变量实现并发

竞态

竞态是指程序在多个goruntine交叉执行操作时,没有给出正确的结果。

三种避免数据竞态的方法:

  • 不要修改变量
  • 避免从多个goruntine访问同一变量
  • 允许多个goruntine访问同一变量,但同一时间只有一个goruntine可以访问。这种叫作互斥机制。

互斥锁:sync.Mutex

读写互斥锁: sync.RWMutex

内存同步

延迟初始化:sync.Once

竞态检测器(the race detector)

只需要在go build , go run或者go test 命令后面加上-race的flag, 就会使编译器创建一个你的应用的”修改“版或者一个附带了能够记录所有运行期对共享变量访问工具的test,并且会记录下每一个读或者写共享变量的goruntine的身份信息。

示例:并发非阻塞缓存

goroutine与线程

动态栈

每一个os线程都有一个固定大小的内存块(一般会使2MB)来作栈,这个栈会用来存储当前正在被调用或者挂起的函数的内部变量。

因为这2MB对于小小的goruntine来说是很大的浪费,创建成百上千的goruntine是非常普遍的,如果每一个goruntine都需要这么大的内存的话,会造成很大的浪费。

一个goruntine会以一个很小的栈开始生命周期,一般只需要2kb。但其不是固定的,最大值有1GB

goruntine调度

因为这种调度方式不需要进入内核的上下文,所以重新调度一个goroutine比调度 一个线程代价要低得多。

GOMAXPROCS

Go的调度器使用了一个叫做GOMAXPROCS的变量来决定会有多少个操作系统的线程同时执行Go的代码。

其默认的值是运行机器上的CPU的核心数。

goruntine没有ID号

在大多数支持多线程的操作系统和程序语言中,当前的线程都有一个独特的身份(id)。goroutine没有可以被程序员获取到的身份(id)的概念。