
题图: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.Condcond = sync.NewCond(&sync.Mutex{})//获取锁cond.L.Lock()//等待通知cond.Wait()//放东西...//释放锁走人cond.L.Unlock()//通知别人,下一个获取锁的cond.Signal()//通知所有人cond.Broadcast()




