请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

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

老师您好!
根据您的讲述,在这里我们之所以会阻塞,是因为我们在第一个任务(打印小写字母)完成后,没有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
}

正在回答 回答被采纳积分+3

2回答

慕仙908892 2021-04-11 23:00:45

你这样不一定每次都能跑完代码~ 小兄弟~ 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 回复 有任何疑惑可以回复我~
ccmouse 2020-12-11 15:24:39

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

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

0 回复 有任何疑惑可以回复我~
  • 上面的代码如果给done = make(chan bool, 2) 是不会deadlock的.这小伙坑你~。他放一个<-workers[len(workers)-1].done本意应该是为了让上面的循环循环到最后,等待读取最后一个done有值,因为上面的for不是gorouting,肯定是要转完的。转完以后等着最后一个work的done被赋值。想着这样程序就能走完,但是他没有考虑到gorouting谁先执行完是不一定的~。所以必须按老师你那样 全部循环一下,才是靠谱的。他这样写有时候是能走完的~
    回复 有任何疑惑可以回复我~ 2021-04-11 22:45:18
  • 哈哈哈,提问的学生真坏
    回复 有任何疑惑可以回复我~ 2021-06-22 23:41:15
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号