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 没有标识

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

相关推荐
小张小张爱学习1 分钟前
Spring Boot 多线程并发入门教程:ThreadPoolTaskExecutor + CompletableFuture
java·spring boot·后端
西安邮电大学4 分钟前
Redis核心数据结构以及应用场景
java·redis·后端·其他·面试
优雅格子衫12 分钟前
uniapp 拍照相册选取后超级好用的裁剪组件,增加水印完全自定义
开发语言·前端·javascript·uni-app·vue
AskHarries22 分钟前
做 SaaS 还是做 App
后端
Vallelonga25 分钟前
Rust 中 unsafe 关键字的语义
开发语言·rust
AI砖家29 分钟前
前端 JavaScript 异步处理全方案详解:从回调到 Observable
开发语言·前端·javascript
思麟呀32 分钟前
C++工业级日志项目(七)日志器核心
linux·开发语言·c++·windows
2401_8734794032 分钟前
如何用IP离线库批量清洗订单IP,自动标注省市区?
开发语言·网络·python
卷无止境34 分钟前
银行里的"等不了"——SimPy Bank Renege 示例全解析
后端
星栈37 分钟前
别再满项目乱丢 String:我开始给领域错误分层了
后端·代码规范