sync.WaitGroup 是如何工作的

主要观点:作者在面试中被同事问到关于sync.WaitGroup的使用问题,意识到自己未完全理解其内部工作原理,遂在周末进行研究并撰写此文。
关键信息:

  • pkg.go.dev的文档开始了解WaitGroup,其用于等待一组协程完成,Add设置要等待的协程数量,Done表示协程完成,Wait用于阻塞直到所有协程完成。
  • sync.WaitGroup的结构体定义包含noCopystatesemanoCopy用于防止值被复制,state存储WaitGroup的状态,sema是信号量值。
  • Add函数用于添加计数器值,Done函数实际上是Add(-1)Wait函数尝试获取信号量值,通过for循环和CompareAndSwap操作来实现。
    重要细节:
  • noCopy通过在接口上实现LockUnlock函数来防止值被复制,go vet会在看到这种情况时发出警告。
  • state的高 32 位存储计数器,低 32 位存储等待者数量。
  • 信号量可以看作一个整数,有acquire(获取)和release(释放)操作,acquire检查信号量值是否大于 0 并递减,release增加信号量值表示资源可用。
  • runtime_Semreleaseruntime_Semacquire是在go代码库中实际实现信号量操作的函数,涉及到协程的暂停和恢复。
  • WaitGroup的内部实现通过原子操作和循环来确保正确的同步和等待。
阅读 10
0 条评论