Dawn's Blogs

分享技术 记录成长

0%

GO学习笔记 (4) sync包实现基本同步操作

sync包

sync包提供了基本的同步基元,如互斥锁。除了OnceWaitGroup类型,大部分都是适用于低水平程序线程高水平的同步使用channel通信更好一些

互斥锁Mutex

1
2
3
type Mutex struct {
// 包含隐藏或非导出字段
}

Mutex是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。

其他类型的同步单元

sync包除了提供互斥锁,还提供了

  • 读写锁RWMutex
  • 条件变量Cond
  • WaitGroupWaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为nDone() 每次把计数器-1wait() 会阻塞代码的运行,直到计数器地值减为0
  • Once(只执行一次动作的对象)

示例

利用sync.Mutex实现对共享变量的互斥访问,利用sync.WaitGroup实现等待各协程运行结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import (
"fmt"
"sync"
)

var (
myMap = make(map[int]int64, 10)
lock sync.Mutex
wg sync.WaitGroup
)

func f(n int) {
// 计算n!
var res int64

res = 1

for i := 1; i <= n; i++ {
res *= int64(i)
}

// 结果存储到map中
lock.Lock()
myMap[n] = res
lock.Unlock()

wg.Done()
}

func main() {
num := 30
wg.Add(num)

for i := 1; i <= num; i++ {
go f(i)
}

wg.Wait() // 等待协程结束运算

// 打印结果
for i, v := range myMap {
fmt.Printf("%d! = %d\n", i, v)
}
}