Go语言程序设计-第9章--使用共享变量实现并发

Go语言程序设计-第9章--使用共享变量实现并发

9.1 竟态

一个能在串行程序中正确工作的函数。如果这个函数在并发调用时仍然能正确工作,那么这个函数是并发安全的。在这里并发调用是指,在没有额外同步机制的情况下,从两个或者多个 goroutine 同时调用这个函数。如果一个类型的所有可访问方法和操作都是并发安全时,则它可称为并发安全的类型。

数据竟态发生于两个 goroutine 并发读写同一个变量,并且至少一个是写入时。有3个方法避免数据竟态。

第一种方法是不要修改变量。

第二种方法是避免多个 goroutine 访问同一个变量。

第三种方法是允许多个 goroutine 访问同一个变量,但是在同一时间只有一个 goroutine 可以访问,这种方法称为互斥机制。

9.2 互斥锁:sync.Mutex

在 Mutex 的 Lock 和 Unlock 之间,可能自由地读取和修改共享变量,这一部分称为临界区域。

9.3 读写互斥锁:sync.RWMutex

仅在绝大部分 goroutine 都在获取读锁并且锁竞争比较激烈时,RWMutex 才有优势。

9.4 内存同步

现代计算机一般会有多个处理器,每个处理器都有内存的本地缓存。为了提高效率,对内存的写入是缓存在每个处理器中的,只有在必要时才刷回内存。甚至刷回内存的顺序都可能与 goroutine 的写入顺序不一致。像通道或者互斥锁操作这样的同步原语都会使处理器把积累的写操作刷回内存并提交。

9.5 延迟初始化: sync.Once

go 复制代码
var loadIconsOnce sync.Once
var icons map[string]image.Image
// 并发安全
func Icon(name string) image.Image {
	loadiconsOnce.Do(loadIcons)
	return icons[name]
}

9.6 竟态检测器

把 -race 命令行添加到 go build, go run, go test 命令里面即可以使用该功能。

9.8 goroutine 与线程

9.8.1 可增长的栈

每个 OS 线程都有一个固定大小的栈内存(通常为 2MB),栈内存区域用于保存在其他函数调用期间哪些正在执行或临时暂停函数中的局部变量。这个固定的栈大小既又太大又太小。对于一个小的 goroutine,2MB的栈是一个巨大的浪费。对于复杂的和深度递归的函数,固定大小的栈始终不够大。

作为对比,一个 goroutine 在生命周期开始只有一个很小的栈,典型情况下为 2KB。与 OS 线程不同的是,goroutine 的栈不是固定大小的,它可以按需增大和缩小。goroutine 的栈可以到达 1GB,比线程典型的固定大小栈高出几个数量级。

Go 运行时包含一个自己的调度器,这个调度器使用一个称为 m:n 调度的技术(因为它可以复用/调度 m 个 goroutine 到 n 个 OS 线程)。Go 调度器与内核调度器的工作类似,但只关心单个 Go 程序的 goroutine 调度问题。

9.8.3 GOMAXPROCS

Go 调度器使用 GOMAXPROCS 参数确定使用多少个 OS 线程来同时执行 Go 代码。默认值是机器上 CPU 的数量。

bash 复制代码
GOMAXPROCS=1 go run hack-cliche.go

9.8.4 goroutine 没有标识

所以没有线程本地变量之类的结构。

相关推荐
m0_748240251 小时前
Windows编程+使用C++编写EXE加壳程序
开发语言·c++·windows
兮兮能吃能睡2 小时前
R语言模型分析(一)(1)
开发语言·r语言
wuk9984 小时前
基于有限差分法的二维平面热传导模型MATLAB实现
开发语言·matlab·平面
熊小猿5 小时前
在 Spring Boot 项目中使用分页插件的两种常见方式
java·spring boot·后端
paopaokaka_luck5 小时前
基于SpringBoot+Vue的助农扶贫平台(AI问答、WebSocket实时聊天、快递物流API、协同过滤算法、Echarts图形化分析、分享链接到微博)
java·vue.js·spring boot·后端·websocket·spring
初见无风6 小时前
2.5 Lua代码中string类型常用API
开发语言·lua·lua5.4
做运维的阿瑞6 小时前
用 Python 构建稳健的数据分析流水线
开发语言·python·数据分析
左师佑图6 小时前
综合案例:Python 数据处理——从Excel文件到数据分析
开发语言·python·数据分析·excel·pandas
陌路206 小时前
C23构造函数与析构函数
开发语言·c++
小蒜学长7 小时前
springboot酒店客房管理系统设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端