Golang的sync.WaitGroup

栏目: Go · 发布时间: 7年前

内容简介:WaitGroup的用途:它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。官方对它的说明如下:A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls D

1.WaitGroup的用途

WaitGroup的用途:它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。

官方对它的说明如下:

A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.

2、WaitGroup的结构

type WaitGroup struct {
    noCopy noCopy

    // 64-bita value: high 32 bits re counter, low 32 bits are waiter count.
    // 64-bit atomic operations require 64-bit alignment, but 32-bit
    // compilers do not ensure it. So we allocate 12 bytes and then use
    // the aligned 8 bytes in them as state, and the other 4 as storage
    // for the sema.
    state1 [3]uint32
}

noCopy字段说明WaitGroup不允许拷贝

state1 高位32位是计数器,低位32位是阻塞等待计数器

剩余的32位用来表示信号量。

3、WaitGroup向外提供的三个函数

Add()

我们来看一个源码中对这个函数的注释:

// Add adds delta, which may be negative, to the WaitGroup counter.
// If the counter becomes zero, all goroutines blocked on Wait are released.
// If the counter goes negative, Add panics.

参数delta可能是负的,加到WaitGroup计数器,可能出现如下结果

如果计数器变为零,所有被阻塞的goroutines都会被释放。

如果计数器变成负数,将会报出一个panic 错误。

Add 源码分析

func (wg *WaitGroup) Add(delta int) {
    statep, semap := wg.state()//获取计数器和信号量指针
    if race.Enabled {
        _ = *statep // trigger nil deref early
        if delta < 0 {
            // Synchronize decrements with Wait.
            race.ReleaseMerge(unsafe.Pointer(wg))
        }
        race.Disable()
        defer race.Enable()
    }
        //将阻塞的 goroutine 计算加delta 
    state := atomic.AddUint64(statep, uint64(delta)<<32)
       //获取计数
    v := int32(state >> 32)
    w := uint32(state)
    if race.Enabled && delta > 0 && v == int32(delta) {
        // The first increment must be synchronized with Wait.
        // Need to model this as a read, because there can be
        // several concurrent wg.counter transitions from 0.
        race.Read(unsafe.Pointer(semap))
    }
    if v < 0 {
              //goroutine 数小于0,抛出错误
        panic("sync: negative WaitGroup counter")
    }

    if w != 0 && delta > 0 && v == int32(delta) {
              // 添加与等待并发调用,报panic
        panic("sync: WaitGroup misuse: Add called concurrently with Wait")
    }
    if v > 0 || w == 0 {
        return
    }
    // This goroutine has set counter to 0 when waiters > 0.
    // Now there can't be concurrent mutations of state:
    // - Adds must not happen concurrently with Wait,
    // - Wait does not increment waiters if it sees counter == 0.
    // Still do a cheap sanity check to detect WaitGroup misuse.
    if *statep != state {
        panic("sync: WaitGroup misuse: Add called concurrently with Wait")
    }
    // Reset waiters count to 0.
    *statep = 0
    for ; w != 0; w-- {
        runtime_Semrelease(semap, false)
    }
}

//


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Google

Google

托马斯·舒尔茨(Thomas·Schulz) / 严孟然、陈琴 / 当代中国出版社 / 2016-11-1 / CNY 49.80

想要掌握未来,必须了解谷歌 1998年从车库起家,短短数年研发上千项专利,2016年力压苹果、亚马逊,成为“世界最具价值品牌”“最佳雇主”,谷歌无疑是互联网时代的最大赢家,这家公司有能力通过巨额广告利润收获现在,更有意愿在人工智能层面创造未来。 据说谷歌势不可挡,永不餍足。从互联网搜索到智能翻译再到地图导航,谷歌是我们通向世界的门户。不仅如此,就像管理全世界的数据流一样,谷歌还要在不久......一起来看看 《Google》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具