暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Go-语言包(Sync)上

花一个无所 2019-09-08
182

题图:Alihanniba

Sync - 共享

一旦数据被多个线程共享,那么就很可能会产生争用和冲突的情况。这种情况也被称为竞态条件,这往往会破坏共享数据的一致性。共享数据的一致性代表着某种约定,即:多个线程对共享数据的操作总是可以达到它们各自预期的效果。同步的用途有两个,一个是避免多个线程在同一时刻操作同一个数据块,另一个是协调多个线程,以避免它们在同一时刻执行同一个代码块。内存临界区总是需要受到保护的,否则就会产生竞态条件。施加保护的重要手段之一,就是使用实现了某种同步机制的工具,也称为同步工具。

在 Go 语言中,可供我们选择的同步工具并不少。其中,最重要且最常用的同步工具当属互斥量(mutual exclusion,简称 mutex)。

sync包中的Mutex就是与其对应的类型,该类型的值可以被称为互斥量或者互斥锁。

一个互斥锁可以被用来保护一个临界区或者一组相关临界区。我们可以通过它来保证,在同一时刻只有一个 goroutine 处于该临界区之内。

    mu.Lock()
    _, err := writer.Write([]byte(data))
    if err != nil {
    log.Printf("error: %s [%d]", err, id)
    }
    mu.Unlock()

    使用互斥锁应该要注意一些事情:

    不要重复锁定互斥锁;不要忘记解锁互斥锁,必要时使用defer语句;不要对尚未锁定或者已解锁的互斥锁解锁;不要在多个函数之间直接传递互斥锁。

    读写锁是读 写互斥锁的简称(RWMutex)

    把读与写区别对待

    对于同一个读写锁来说

    在写锁被锁定的情况下试图锁定写锁,会阻塞当前的goroutine在写锁被锁定的情况下试图锁定读锁,会阻塞当前的goroutine在读锁被锁定的情况下试图锁定写锁,会阻塞当前的goroutine在读锁被锁定的情况下试图锁定读锁,不会阻塞当前的…………..

    可以一句话概括:对于某个受到读写锁保护的共享资源,多个写操作不能同时进行,写操作和读操作也不能同时进行,但多个读操作却可以同时进行。

    对写锁进行解锁,会唤醒“所有因试图锁定读锁,而被阻塞的 goroutine”,并且,这通常会使它们都成功完成对读锁的锁定。

    互斥锁跟读写锁的指针类型都实现了Locker接口

    获取读写锁的读锁

      func (rw *RWMutex) RLocker() Locker

      条件变量sync.Cond

      Cond 是 跟互斥锁一起出现的Cond 的三个方法 func NewCond(l Locker) *Cond

      等待通知(wait)func (c *Cond) Wait()单发通知(signal)func (c *Cond) Signal()广播通知(broadcast)func (c *Cond) Broadcast()


      每个Cond都会关联一个Locker,当修改条件或者调用wait方法时必须加锁保护condition

        var cond *sync.Cond
        cond = sync.NewCond(&sync.Mutex{})
        //获取锁
        cond.L.Lock()
        //等待通知
        cond.Wait()
        //放东西
        ...
        //释放锁走人
        cond.L.Unlock()
        //通知别人,下一个获取锁的
        cond.Signal()
        //通知所有人
        cond.Broadcast()
        文章转载自花一个无所,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论