Golang 之sync包应用

sync.Mutex

保证共享资源的互斥访问

mutex := &sync.Mutex{}
mutex.Lock()
// Update共享变量 (比如切片,结构体指针等)
mutex.Unlock()

sync.RWMutex

读写互斥锁,可以对读加锁

mutex := &sync.RWMutex{}
mutex.Lock()
// Update 共享变量
mutex.Unlock()

mutex.RLock()
// Read 共享变量
mutex.RUnlock()

sync.WaitGroup

使用Add()添加计数,Done()减掉一个计数,计数不为0, 阻塞Wait()的运行

将数组每个值取平方,最后求所有的值的和,可以开数组大小的协程,用sync控制所有的协程都计算完成

package main

import (
    "fmt"
    "sync"
)

func opera(a int, taskres chan int, wg *sync.WaitGroup) {
    taskres <- a * a
    wg.Done()
}
func main() {
    a := []int{3, 5, 4, 7, 3, 8, 1}
    taskres := make(chan int, len(a))
    var wg sync.WaitGroup
    for _, v := range a {
        wg.Add(1)
        go opera(v, taskres, &wg)
    }
    wg.Wait()
    close(taskres)
    var result int = 0
    //range只能for关闭了的channel
    for i := range taskres {
        result += i
    }
    fmt.Println(result)
}

sync.Map

sync.Pool

sync.Once

保证一个函数仅被执行一次

once := &sync.Once{}
for i := 0; i < 4; i++ {
    i := i
    go func() {
        once.Do(func() {
            fmt.Printf("first %d\n", i)
        })
    }()
}

sync.Cond

用于goroutine之间的协作,用于协程的挂起和唤醒。

避免轮训空等,待着就好,wait别人signal你

func main() {
    cond := sync.NewCond(new(sync.Mutex))
    condition := 0

    // Consumer
    go func() {
        for {
            cond.L.Lock()
            for condition == 0 {
                cond.Wait()
            }
            condition--
            fmt.Printf("Consumer: %d\n", condition)
            cond.Signal()
            cond.L.Unlock()
        }
    }()

    // Producer
    for {
        time.Sleep(time.Second)
        cond.L.Lock()
        for condition == 3 {
            cond.Wait()
        }
        condition++
        fmt.Printf("Producer: %d\n", condition)
        cond.Signal()
        cond.L.Unlock()
    }
}
输出:
Producer: 1
Consumer: 0
Producer: 1
Consumer: 0
Producer: 1
Consumer: 0
Producer: 1
Consumer: 0
Producer: 1
Consumer: 0

 

posted @ 2020-07-30 20:02  LeeJuly  阅读(194)  评论(0编辑  收藏  举报