适用于并发查询计算等业务场景。
使用channel
1 | // channel |
上文首先定义了包含5个数字的int32
型Slice以及对应长度类型的Channel;然后分5个Goroutine对Slice中的每个数字进行自增运算形成新的Slice并输出。运行结果为(并发输出顺序随机,以下只是其中一种可能):
1 | results is: [2 3 6 2 5] |
该方法的基本思想是:将每个Goroutine的处理结果通过Chan传到指定Goroutine,使用select语句收集传输过来的内容。属于”以通讯共享内存”的内容安全策略。
注意:Channel的收发个数要保持一致,当收多于发时会造成死锁,最好添加超时语句做异常情况保护case <-time.After(10 * time.Second):
。
使用sync.WaitGroup
1 | // waitGroup |
功能与第一段代码相同,运行结果:
results is: [5 1 2 3 4]
该方法的基本思想是:声明一个长度为len
的sync.WaitGroup
队列wg
,各个Goroutine中每执行一次wg.Done()
队列长度减1,wg.Wait()
会对队列长度进行判断,为0时程序才往下进行。该方法直接对内存进行了共享。
注意:wg.Add(len)
中的len应等于wg.Done()
的执行次数,len一直未置0会造成死锁。
另: 由于append()
函数非并发安全,需要添加并发锁sync.Mutex
。
–
建议:从实际使用的角度来说使用WaitGroup会使代码更为简洁,但从内容安全以及设计者初衷来说应选择使用channel。