golang包学习之sync

golang中sync包实现了两种功能的锁Mutex(互斥锁)和RWMutex(读写锁)
type Mutex
func (m *Mutex) Lock()
func (m *Mutex) Unlock()
type RWMutex
func (rw *RWMutex) Lock()
func (rw *RWMutex) RLock()
func (rw *RWMutex) RLocker() Locker
func (rw *RWMutex) RUnlock()
func (rw *RWMutex) Unlock()

  1. Mutex
    重复Lock(),会引起死锁。
    fatal error: all goroutines are asleep - deadlock!
    Unlock()之前,并未Lock(),会引起一个运行时的错误。
    panic: sync: unlock of unlocked mutex
    适用场景:读写次数不确定,并且只允许一个读或写的场景,又称为全局锁
  2. RWMutex
    写锁加锁:如果在添加写锁之前,已有写锁或者读锁,则Lock()会阻塞直至之前持有的锁被释放,写锁权限高于读锁,有写锁时优先进行写锁定。
    func (rw *RWMutex) Lock()
    写锁解锁:如果解锁之前未加锁,会引起一个运行时的错误。
    func (rw *RWMutex) Lock()
    panic: sync: Unlock of unlocked RWMutex

    读锁加锁:当只存在读锁或者不存在写锁的时候才能使用读锁加锁,存在写锁的时候无法使用读锁。
    func (rw *RWMutex) RLock()
    读锁解锁:读锁解锁,撤销单次Rlock()的操作
    func (rw *RWMutex) RUnlock()
    适用场景:读次数远远多于写的场景

WaitGroup

type WaitGroup
func (wg *WaitGroup) Add(delta int)
func (wg *WaitGroup) Done()
func (wg *WaitGroup) Wait()

使用sync.WaitGroup,等待多个goroutine结束。通过设定计数器,让每个goroutine在推出前递减,直至归零解除阻塞。

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg. Add(1)                //累加计数
        go func(id int) {
            defer wg.Done()       //递减计数
            time.Sleep(time.Second)
            prointln("goroutine", id, "done.")
        }(i)
    }
    println("main...")
    wg.Wait()                    //阻塞,直到计数归零
    println("main exit...")

注意:
* 虽然WaitGroup.Add实现了原子操作,但建议在goroutine外累加计数器。避免Add未执行,Wait已经退出的情况。
* 可以在多处使用Wait阻塞,它们都能够接收到通知。

你可能感兴趣的:(go语言)