接收两次worker.done是否刚需?

来源:11-2 使用Channel等待任务结束

xfcy_晓风残月

2020-12-07

老师您好!
根据您的讲述,在这里我们之所以会阻塞,是因为我们在第一个任务(打印小写字母)完成后,没有goroutine再去接收worker.done发出的东西,所以造成阻塞。
根据您的代码,我做了两个实验:
#实验一# 我们去收整个队列中的最后一个done不就能解决这个问题了,我用-race查看之后也没有数据冲突。
#实验二# 我们去收整个队列的一次done,第二个任务(打印大写字母)发出的done就不理会了,同样也没有出现数据冲突。
代码展示:

func chanDemo() {
	var workers [26]worker
	for i := range workers {
		workers[i] = createWorker(i)
	}

	for i := range workers {
		workers[i].in <- 'a' + i
	}
	for i := range workers {
		workers[i].in <- 'A' + i
	}

	// 实验二:
	//for i := 0; i < len(workers); i++ {
	//	<-workers[i].done
	//}
	// 实验一:
	<-workers[len(workers)-1].done
}
写回答

2回答

慕仙908892

2021-04-11

你这样不一定每次都能跑完代码~ 小兄弟~ gorouting 谁先执行完是不一定的。而for循环的意义在于他是从第0个开始检测。10太长,我给你举个5个的例子吧~如果执行完的顺序是 1,2,5, 4, 3.你这样写,后面2个你就跑不完,循环的意义在于他先从第1个开始,1有就输出1 2有了就输出2 3这个时候没有就会等待,因为先执了完了5和4,然后这个时候3有了,输出3,5和4之前执行完了,现在直接就显示4 和 5了 。明白吧~,<-done的意义在于他如果没有值,会在那等待的~,chan你可以把他叫作管道,水管,有进就得有出,如果你把doworker中的 done <- true去掉,他就会deadlock。因为没水进来。GO底层会检测,如果你只有出没有进就会报错。

1
0

ccmouse

2020-12-11

不知道你的实验一和实验二是加在最后还是什么地方。我试了一下加在最后,会报deadlock。可以考虑把完整代码贴一下。

阻塞的问题,的确有很多种解法。我这里必须收这20个(视频中是10个小写,10个大写)done,这是前提,然后再考虑如何不阻塞的收到这20个done

0
2
尼克2018
回复
慕仙908892
哈哈哈,提问的学生真坏
2021-06-22
共2条回复

Google资深工程师深度讲解Go语言 由浅入深掌握Go语言

语法+分布式爬虫实战 为转型工程师量身打造

5995 学习 · 1909 问题

查看课程