typora/note/Go/sync包.md
2024-12-12 10:48:55 +08:00

77 lines
2.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### sync 包低级同步原语使用场景
- 高性能的临界区critical section同步机制场景
- 不想转移结构体对象所有权,但又要保证结构体内部状态数据的同步访问的场景
### sync包原语使用注意事项
- 不要将原语复制后使用
- 用闭包或者传递原语变量的地址(指针)
### mutex 互斥锁
- 零值可用,不用初始化
- LockUnlock
- lock状态下任何goroutine加锁都会阻塞
### RWMutex 读写锁
- 零值可用,不用初始化
- RLockRUnlock 加读锁,解读锁
- LockUnlock 加写锁,解写锁
- 加读锁状态下,不会阻塞加读锁,会阻塞加写锁
- 加写锁状态下会阻塞加读锁与写锁的goroutine
### sync.Cond 条件变量
- sync.Cond是传统的条件变量原语概念在 Go 语言中的实现
- 可以把一个条件变量理解为一个容器,这个容器中存放着一个或一组等待着某个条件成立的 Goroutine
- 当条件成立后,处于等待状态的 Goroutine 将得到通知,并被唤醒继续进行后续的工作
```go
type signal struct{}
var ready bool
func worker(i int) {
fmt.Printf("worker %d: is working...\n", i)
time.Sleep(1 * time.Second)
fmt.Printf("worker %d: works done\n", i)
}
func spawnGroup(f func(i int), num int, groupSignal *sync.Cond) <-chan signal {
c := make(chan signal)
var wg sync.WaitGroup
for i := 0; i < num; i++ {
wg.Add(1)
go func(i int) {
groupSignal.L.Lock()
for !ready {
groupSignal.Wait()
}
groupSignal.L.Unlock()
fmt.Printf("worker %d: start to work...\n", i)
f(i)
wg.Done()
}(i + 1)
}
go func() {
wg.Wait()
c <- signal(struct{}{})
}()
return c
}
func main() {
fmt.Println("start a group of workers...")
groupSignal := sync.NewCond(&sync.Mutex{})
c := spawnGroup(worker, 5, groupSignal)
time.Sleep(5 * time.Second) // 模拟ready前的准备工作
fmt.Println("the group of workers start to work...")
groupSignal.L.Lock()
ready = true
groupSignal.Broadcast()
groupSignal.L.Unlock()
<-c
fmt.Println("the group of workers work done!")
}
```