Go语言并发安全锁 | 青训营笔记

63 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第12天

开启了两个 goroutine 分别执行 add 函数,这两个 goroutine 在访问和修改全局的x变量时就会存在数据竞争,某个 goroutine 中对全局变量x的修改可能会覆盖掉另一个 goroutine 中的操作

互斥锁

保证同一时间只有一个 goroutine 可以访问共享资源

用sync包中提供的Mutex类型来实现互斥锁 (完全互斥的)

func (m *Mutex) Lock()        获取互斥锁

func (m *Mutex) Unlock()    释放互斥锁

var (
        x int64
        wg sync.WaitGroup // 等待组
        m sync.Mutex // 互斥锁)

// add 对全局变量x执行5000次加1操作func add() {
        for i := 0; i < 5000; i++ {
                m.Lock() // 修改x前加锁
                x = x + 1
                m.Unlock() // 改完解锁
        }
        wg.Done()}

读写互斥锁

var rwm sync.RWMutex

func (rw *RWMutex) Lock()                         获取写锁

func (rw *RWMutex) Unlock()                     释放写锁

func (rw *RWMutex) RLock()                       获取读锁

func (rw *RWMutex) RUnlock()                   释放读锁

func (rw *RWMutex) RLocker() Locker        返回一个实现Locker接口的读写锁

sync.WaitGroup

声明:   

var wg sync.WaitGroup

func (wg * WaitGroup) Add(delta int)        计数器+delta

(wg *WaitGroup) Done()                            计数器-1

(wg *WaitGroup) Wait()                             阻塞直到计数器变为0

sync.Once

确保某些操作即使在高并发的场景下也只会被执行一次,如init

func (o *Once) Do(f func())

var loadOnce sync.Once
loadOnce.func(loadpic)

sync.Once实现的并发安全的单例模式

type singleton struct {}
var instance *singleton
var once sync.Once

func GetInstance() *singleton {
    once.Do(func() {
        instance = &singleton{}
    })
    return instance
}

sync.Once其实内部包含一个互斥锁和一个布尔值:

互斥锁保证布尔值和数据的安全,而布尔值用来记录初始化是否完成。

sync.Map

Go 语言中内置的 map 不是并发安全的, 不能在多个 goroutine 中并发对内置的 map 进行读写操作

// 并发安全的map: var m = sync.Map{}

func (m *Map) **Store**(key, value interface{})    存储key-value数据

func (m *Map) **Load**(key interface{}) (value interface{}, ok bool)    查询key对应的value

func (m *Map) **LoadOrStore**(key, value interface{}) (actual interface{}, loaded bool)    查询或存储key对应的value

func (m *Map) **LoadAndDelete**(key interface{}) (value interface{}, loaded bool)    查询并删除key

func (m *Map) **Delete**(key interface{})    删除key

func (m *Map) **Range**(f func(key, value interface{}) bool)    对map中的每个key-value依次调用f

原子操作

由内置的标准库sync/atomic提供