sync.WaitGroup

WaitGropu使用注意

作groutine参数时传指针

type WaitGroup struct {
	noCopy noCopy

	// 64-bit value: high 32 bits are 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
}

WaitGroup 是结构体,传入使用值拷贝时,groutine内外是两个不同的WaitGroup,会造成逻辑混乱

var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(i int, wg *sync.WaitGroup) {
			fmt.Println(i)
			defer wg.Done()
		}(i, &wg)
	}
	wg.Wait()

WaitGroup的Add要在goroutine前执行

var wg sync.WaitGroup
	for i := 0; i < 10; i++ {

		go func(i int, wg *sync.WaitGroup) {
			wg.Add(1)//应该在开始gorroutine之前调用wg.Add(1)来避免数据读写竞争
			fmt.Println(i)
			defer wg.Done()
		}(i, &wg)
	}
	wg.Wait()

Add传入任意数字

var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1000)
		go func(i int, wg *sync.WaitGroup) {
			fmt.Println(i)
			defer wg.Done()
		}(i, &wg)
	}
	wg.Wait()

在使用上不会有什么问题,源码中根据输入的参数循环发送信号量;如果在高并发场景下会有性能问题;

WaitGroup的实现核心是 CAS使用
借用了CPU提供的原子性指令来实现。CAS操作修改共享变量时候不需要对共享变量加锁,而是通过类似乐观锁的方式进行检查,本质还是不断的占用CPU 资源换取加锁带来的开销(比如上下文切换开销)

posted @ 2021-10-03 15:20  wangzhilei  阅读(121)  评论(0编辑  收藏  举报