go sync包
在一个 goroutine 中,如果分配的内存没有被其他 goroutine 访问,只在该 goroutine 中被使用,不存在资源竞争的问题。但如果同一块内存被多个 goroutine 同时访问,就会不知道谁先访问,也无法预料最后结果。这就产生了资源竞争,这块内存就是共享资源。channel 是并发安全的,内部自加了锁,但是很多变量或者资源没有加锁,就需要 sync 同步原语了(相关资料)
类似 go build、go run、go test,这种 Go 工具链命令,添加 -race 标识,帮助检查 Go 语言代码是否存在资源竞争。
go run -race gosrc.go
waitgroup
用于最终完成的场景,关键点在于一定是等待所有协程都执行完毕。
1 声明一个 WaitGroup,通过 Add 方法设置一个计数器的值,需要跟踪多少协程就设置多少,Add()设置的值必须与实际等待的goroutine个数一致,否则会panic。
2 每个协程在执行完毕的时候,一定要调 Done 方法,让计数器减1,告诉 WaitGroup 该协程已经执行完毕。
3 最后调用 Wait 方法,一直等待,直到计数器的值变为0,也就是所有跟踪的协程执行完毕了。
踩坑事项
在文章的最后总结一下使用waitGroup易错的知识点,防止大家再次犯错。
waitGroup中计数器的值是不能小于0的,源码中我们就可以看到,一旦小于0就会引发panic。
一定要住注意调用Add方法与Wait方法的顺序,不可并发同时调用这两个方法,否则就会引发panic,同时在调用了wait方法在其没有释放前不要再次调用Add方法,这样也会引发panic,waitGroup是可以复用的,但是需要保证其计数周期的完整性。
WaitGroup对象不是一个引用类型,通过函数传值的时候需要使用地址,因为Go语言只有值传递,传递WaitGroup是值的话,就会导致会发生panic
once
用once可以保证上面的onc.Do()被执行一次 执行一次之后其他的协程就不会执行了cond
cond其实就是哪个控制协程执行的包函数:让哪个执行,让全部执行,给函数标注,让函数等待执行、 加锁等Signal是执行一个协程的信号
Broadcast是执行全部协程的信号
wait 协程等待通知,阻塞在此
NewCond创建条件
cond.L.Lock() 给协程加锁
cond.L.Unlock() //释放锁
pool
pool就是一个类似中间件的 存放东西的put放入
get取出
New为走默认值
RWMUX
RWMUX是控制多个协程对于资源的使用顺序的RLOCK RULOCK
LOCK ULOCK
在一个协程里面
对资源的
读锁的时候别的协程也可以读,但是不可以写
写锁的时候别的协程不可以操作,不可以读也不可以写
Mutex
多个协程会操作一个特定资源,就会出现意想不到的错误,所以我们使用互斥锁,一个协程使用特定资源的时候进行锁定,用完解锁,
再让其他协程使用,所以其他协程想使用此资源,必须自己给资源解锁或等待正在使用的协程解锁
在代码中就是锁定一段代码,代码里面有资源
type Cond
func NewCond(l Locker) *Cond
func (c *Cond) Broadcast()
func (c *Cond) Signal()
func (c *Cond) Wait()
type Locker
type Mutex
func (m *Mutex) Lock()
func (m *Mutex) Unlock()
type Once
func (o *Once) Do(f func())
type Pool
func (p *Pool) Get() interface{}
func (p *Pool) Put(x interface{})
type RWMutex
func (rw *RWMutex) Lock()
func (rw *RWMutex) RLock()
func (rw *RWMutex) RLocker() Locker
func (rw *RWMutex) RUnlock()
func (rw *RWMutex) Unlock()
type WaitGroup
func (wg *WaitGroup) Add(delta int)
func (wg *WaitGroup) Done()
func (wg *WaitGroup) Wait()
本文来自博客园,作者:给香菜送点香菜,转载请注明原文链接:https://www.cnblogs.com/mingkewang/articles/17160171.html

浙公网安备 33010602011771号