Sync
互斥量:sync.Mutex
读写锁:sync.RWmutex
条件变量:sync.cond
锁
锁的粒度越小越好
一个Goroutine访问在访问一个资源时,先将该资源锁住,防止其他Goroutine访问。访问完毕后解锁。其他Goroutine再来加锁访问。
//锁是自愿的。
// 锁锁定的是加锁和解锁内所有内容
互斥锁:
建议锁,不具有强制性。
保护公共数据。被锁住后,只有成功加锁的Goroutine能正常访问。其他go程阻塞在锁的等待事件上。
// 定义
var l sync.Mutex
// 加锁
l.Lock()
// 解锁
l.Unlock()
读写锁:
读共享,写独占。
写锁优先级高于读锁。
锁只有一把,但是有两种属性。读属性加锁、写属性加锁。
// 定义
var rwl sync.RWMutex
// 加锁
rwl.RLock() rwl.Lock()
// 解锁
rwl.RUnlock rwl.UnLock()
死锁:
channel 读写有一端永远无法执行
条件变量:
多个Goroutine对同一个资源进行读写,以读操作为例,Goroutine拿到资源后对资源进行加锁操作,如遇到无资源可读的情况进入Wait状态,阻塞并释放锁。(这一步是原子操作)然后等待被写操作唤醒,写操作拿到Goroutine后执行加锁,写入数据后发送signal唤醒读端。然后解锁。
// 创建条件变量
var cond sync.Cond
// 给条件变量的成员 L 初始化互斥锁
cond.L = new(sync.Mutex)
// 给条件变量的成员L加锁
cond.L.Lock()
// 判断条件变量是否满足
// 如果满足
cond.Wait() // 123 功能
// 1 阻塞
// 2 释放锁 // 这里是为了让对端可以对数据进行操作
// 3 等待被唤醒,被唤醒则停止阻塞 // 对端对数据进行操作后,会唤醒
// 发送信号唤醒阻塞在条件变量上的消费者
cond.Signal()
// 解锁
cond.L.Unlock()