Golang✔️走进 Go 语言✔️ 第二十课 原子操作 & 互斥体
Posted 我是小白呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang✔️走进 Go 语言✔️ 第二十课 原子操作 & 互斥体相关的知识,希望对你有一定的参考价值。
概述
Golang 是一个跨平台的新生编程语言. 今天小白就带大家一起携手走进 Golang 的世界. (第 20 课)
协程存在的问题
当大量的协程并发的时候, 会产生资源抢占冲突.
例子:
package main
import (
"fmt"
"time"
)
func main() {
// 定义原子变量整数
var ops uint64 = 0
// 创建一坨协程
for i := 0; i < 10; i++ {
go func() {
for j := 0; j < 10000; j++ {
// 线程冲突, 数据不精确
ops += 1
}
}()
}
// 等待
time.Sleep(time.Second * 5)
// 调试输出
fmt.Println(ops)
}
输出结果:
69980
我们可以看到, 输出的结果是 69980, 而非 100000, 原因是线程冲突导致数据不精确.
原子操作
atomic 提供的原子操作使得我们能够确保任一时刻只有一个协程 (go routine) 对变量进行操作. 善用 atomic 能够避免程序中出现大量的锁操作.
例子:
package main
import (
"fmt"
"sync/atomic"
"time"
)
func main() {
// 定义原子变量整数
var ops uint64 = 0
//
for i := 0; i < 10; i++ {
go func() {
for j := 0; j < 10000; j++ {
// 避免线程冲突
atomic.AddUint64(&ops, 1)
}
}()
}
// 等待
time.Sleep(time.Second * 5)
// 调试输出
fmt.Println(ops)
}
输出结果:
100000
互斥锁
互斥锁 (Mutex) 用于主动控制元素的变量在同一时间只能被一个协程访问.
Mutex 有两个方法:
- func (*Mutex) Lock: Lock 方法锁住 m, 如果 m 已经加锁, 则阻塞到 m 解锁
- func (*Mutex) Unlock: Unlock 方法解锁 m, 如果 m 未加锁会导致运行时错误
例子:
package main
import (
"fmt"
"math/rand"
"sync"
"sync/atomic"
"time"
)
func main() {
var state = make(map[int]int) // 状态
var mutex = &sync.Mutex{} // 互斥锁
var readops uint64 = 0 // 读取数据
var writeops uint64 = 0 // 写入数据
// 循环读取
for i := 0; i < 100; i++ {
go func() {
total := 0
for {
key := rand.Intn(5)
mutex.Lock() // 加锁
total += state[key] // 数据叠加
mutex.Unlock() // 解锁
atomic.AddUint64(&readops, 1) // 记录读取次数
time.Sleep(time.Millisecond)
}
}()
}
// 循环写入
for i := 0; i < 10; i++ {
go func() {
for {
key := rand.Intn(5)
val := rand.Intn(100)
mutex.Lock() // 加锁
state[key] = val // 写入数据
mutex.Unlock() // 解锁
atomic.AddUint64(&writeops, 1) // 写入次数
time.Sleep(time.Millisecond)
}
}()
}
// 休眠1秒
time.Sleep(time.Second * 1)
// 调试输出
read := atomic.LoadUint64(&readops)
write := atomic.LoadUint64(&writeops)
fmt.Println(read)
fmt.Println(write)
mutex.Lock()
fmt.Println(state)
mutex.Unlock()
}
输出结果:
5179
519
map[0:36 1:67 2:62 3:86 4:68]
以上是关于Golang✔️走进 Go 语言✔️ 第二十课 原子操作 & 互斥体的主要内容,如果未能解决你的问题,请参考以下文章
Golang✔️走进 Go 语言✔️ 第二十四课 TCP 高阶操作
Golang✔️走进 Go 语言✔️ 第二十四课 TCP 高阶操作