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()

 

posted @ 2023-02-27 16:19  给香菜送点香菜  阅读(93)  评论(0)    收藏  举报