s********k 发帖数: 6180 | 1 感觉两种sync方法差不多,不太了解两者用起来差别在哪里,比如下面这个简单例子
1,用channel
ch := make(chan int,n)
for i:=0; i < n; i++ {
go func() {
// do something
ch <- i
}
}
for i:=0; i < n; i++ {
<- ch
}
2. 用wait group
var wg WaitGroup
wg.Add(n)
for i:=0; i < n; i++ {
go func() {
defer wg.Done()
// do something
}
}
wg.Wait()
效果来说应该差不多,也许性能有点差异暂时可以忽略,但是两者方法来说有什么显著
差别吗? |
f*******o 发帖数: 1 | 2 个人觉得第一种做法并不实用因为这里知道你需要从chan等的数据的个数, 实际中很少
是这样
我经常做的是把waitGroup放到consumer而不是producer。主线程spin producer和
consumer之后用wg等待。 producer在完成向chan输送数据之后close(ch),而consumer
通过测试<-ch的第二个返回值来决定是否还有data (data, ok := <-ch),没有data之
后wg.Done()来告诉主线程是否结束等待。
第一个例子还有个很tricky的错误,ch <- i 这个 i 在循环的时候一直在改变,所以
在go func里面的传给ch的时候 i 已经是下一个甚至几个循环的值,所以很可能传了一
堆n-1给ch,正确的用法是传值go func(i int) {...}(i)。例子里面go func(){}之后
缺了()可能是促成这个错误的原因。 |
w********m 发帖数: 1137 | 3 我感觉他们的场景不一样。
blocking channel 见到的,是用在只有一个go routine的情况。
而wg.Wait用在多个go rountine。
还有一个方法就是楼上说的,close channel。 |
s********k 发帖数: 6180 | 4 如果我知道这个chan的个数的话,两者相比起来哪个比较好?因为我没有专门close
channel,最后是不是GC会自动回收那部分?听起来这样的额话用wait group好一点?
consumer
【在 f*******o 的大作中提到】 : 个人觉得第一种做法并不实用因为这里知道你需要从chan等的数据的个数, 实际中很少 : 是这样 : 我经常做的是把waitGroup放到consumer而不是producer。主线程spin producer和 : consumer之后用wg等待。 producer在完成向chan输送数据之后close(ch),而consumer : 通过测试<-ch的第二个返回值来决定是否还有data (data, ok := <-ch),没有data之 : 后wg.Done()来告诉主线程是否结束等待。 : 第一个例子还有个很tricky的错误,ch <- i 这个 i 在循环的时候一直在改变,所以 : 在go func里面的传给ch的时候 i 已经是下一个甚至几个循环的值,所以很可能传了一 : 堆n-1给ch,正确的用法是传值go func(i int) {...}(i)。例子里面go func(){}之后 : 缺了()可能是促成这个错误的原因。
|
s********k 发帖数: 6180 | 5 对的,我没有写明白,第一个应该用closure这样的,go func(i int) {...}(i),我现
在并没有出BUG,只是想知道两种方法比较哪种合适?
consumer
【在 f*******o 的大作中提到】 : 个人觉得第一种做法并不实用因为这里知道你需要从chan等的数据的个数, 实际中很少 : 是这样 : 我经常做的是把waitGroup放到consumer而不是producer。主线程spin producer和 : consumer之后用wg等待。 producer在完成向chan输送数据之后close(ch),而consumer : 通过测试<-ch的第二个返回值来决定是否还有data (data, ok := <-ch),没有data之 : 后wg.Done()来告诉主线程是否结束等待。 : 第一个例子还有个很tricky的错误,ch <- i 这个 i 在循环的时候一直在改变,所以 : 在go func里面的传给ch的时候 i 已经是下一个甚至几个循环的值,所以很可能传了一 : 堆n-1给ch,正确的用法是传值go func(i int) {...}(i)。例子里面go func(){}之后 : 缺了()可能是促成这个错误的原因。
|
s********k 发帖数: 6180 | 6 假设我现在就一个channel,那么如果不去close但是用完了之后golang的GC会去自己
close并且回收?
【在 w********m 的大作中提到】 : 我感觉他们的场景不一样。 : blocking channel 见到的,是用在只有一个go routine的情况。 : 而wg.Wait用在多个go rountine。 : 还有一个方法就是楼上说的,close channel。
|
c****f 发帖数: 1102 | 7 程序结束channel自己就关掉了
其实这个真的很搞
buffed channel不需要等receiver
unbuffed channel一定要有receiver 不然直接deadlock
如果不想知道你channel大小用sync是可以的 但是做法一般就是
把sender和receiver全部做成groutine 主程序自己放个for{}就好了 |
s********k 发帖数: 6180 | 8 我这里比如都是buffered channel,感觉好像wait group和channel差不多,有点疑惑
,我看前面说在不知道channel多少input时候用wait group,但是你在wait group也会
指定add的数量啊。本质上和for loop一个意思。
你的程序结束比如我在这个goroutine开的channel,这个goroutine结束之后channel和
其他variable同等被回收了?
【在 c****f 的大作中提到】 : 程序结束channel自己就关掉了 : 其实这个真的很搞 : buffed channel不需要等receiver : unbuffed channel一定要有receiver 不然直接deadlock : 如果不想知道你channel大小用sync是可以的 但是做法一般就是 : 把sender和receiver全部做成groutine 主程序自己放个for{}就好了
|
w********m 发帖数: 1137 | 9 我的意思是实现一个pattern。比如 https://play.golang.org/p/sYowzPo4kZt
【在 s********k 的大作中提到】 : 假设我现在就一个channel,那么如果不去close但是用完了之后golang的GC会去自己 : close并且回收?
|
f*******t 发帖数: 7549 | 10 看起来是等价的。
为啥一定要问出个区别呢,编程就是同样的功能有多种写法啊 |
|
|
s********k 发帖数: 6180 | 11 我也是按照等价来默认写code的(针对一个channel并且知道buffer size情况),只是
问一下有没有不了解被忽略的区别
【在 f*******t 的大作中提到】 : 看起来是等价的。 : 为啥一定要问出个区别呢,编程就是同样的功能有多种写法啊
|
f*******t 发帖数: 7549 | 12 说不定waitgroup就是这么实现的
【在 s********k 的大作中提到】 : 我也是按照等价来默认写code的(针对一个channel并且知道buffer size情况),只是 : 问一下有没有不了解被忽略的区别
|
s********k 发帖数: 6180 | 13 好主意,去看看lib实现
【在 f*******t 的大作中提到】 : 说不定waitgroup就是这么实现的
|
f*******t 发帖数: 7549 | 14 看了一下源码,实现还是不一样的
【在 s********k 的大作中提到】 : 好主意,去看看lib实现
|
s********k 发帖数: 6180 | 15 对的,我也发现了,我现在觉得两者其实是实用不同场景,而且经常会混合起来一起用
【在 f*******t 的大作中提到】 : 看了一下源码,实现还是不一样的
|
d********f 发帖数: 8289 | 16 我一般能用channel的地方不用wait group
【在 s********k 的大作中提到】 : 感觉两种sync方法差不多,不太了解两者用起来差别在哪里,比如下面这个简单例子 : 1,用channel : ch := make(chan int,n) : for i:=0; i < n; i++ { : go func() { : // do something : ch <- i : } : } : for i:=0; i < n; i++ {
|