杰克工作室 发表于 2023-3-1 11:01

为啥使用chan时,输出结果不固定

<p><img alt="chan为啥运行的结果不固定.jpg" src="data/attachment/forum/202303/01/6758f1082383121da231917cdf6e54a6.jpg" title="16617564501661756450_3997.jpg" /></p>

<p>&nbsp;</p>

<p>请认真回答以下问题:</p>

<p>1、为啥输出结果不固定?会出现死锁吗?会一直运行下去吗?</p>

<p>2、第10行代码打开后,请写出输出结果?</p>

<p>3、将第25行代码注释后,打开第10行代码,程序可以输出什么?为什么?</p>

<p>4、第10行代码打开,将第14行代码与第15行代码互换后,会影响结果输出吗?那输出结果会是什么呢?</p>

杰克工作室 发表于 2023-3-1 11:02

1、从图中看,不固定输出应该是指多的1,由于25行阻塞的缘故,使得第一个协程执行,但此协程执行到第14行,通道结束阻塞,第15行还没还得及输出,主协程已经执行完毕,于是协程1不一定能够执行到第15行,也有可能因为阻塞竞争关系,会输出第15行的结果。

不会出现死锁。

不会一直运行下去,但如果多次连续运行,协程异步执行未结束,又开始新的协程,可能会锁死进程,导致一直运行下去,简单的方法就是间隔超过1秒即可。



2、会输出图中的所有fmt.Println结果

3、会输出1111---lock 1,这个1可能也不输出。因为18行进行阻塞,使得协程1执行。执行完第二个协程时,主协程没有阴塞同时也执行完了,导致协程2只能在后台运行,无法将结果输出到前端。

4、第14行与第15行代码互换后,会影响输出结果。打开第10行代码,将出输出所有fmt.Println结果。

杰克工作室 发表于 2023-3-1 11:02

https://zhuanlan.zhihu.com/p/397669964

https://zhuanlan.zhihu.com/p/385371995


以上为代码原型,主要用来了解goroute。

杰克工作室 发表于 2023-3-1 11:03

补充1楼,源代码:
<pre>
package&nbsp;main
&nbsp;
import&nbsp;(
&nbsp;&nbsp;&nbsp;&nbsp;&quot;time&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&quot;fmt&quot;
)
&nbsp;
func&nbsp;main()&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;ch&nbsp;:=&nbsp;make(chan&nbsp;struct{},&nbsp;1)
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;ch&nbsp;&lt;-&nbsp;struct{}{}&nbsp;//有1个缓冲可以用,无需阻塞,可以立即执行
&nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;func()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//子协程1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(&quot;1111----lock&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.Sleep(2&nbsp;*&nbsp;time.Second)&nbsp;//sleep一个很长的时间
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;-ch
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(&quot;1&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;}()
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;ch&nbsp;&lt;-&nbsp;struct{}{}&nbsp;//由于子协程1已经启动,寄希望于子协程1帮自己解除阻塞,所以会一直等子协程1执行结束。如果子协程1执行结束后没帮自己解除阻塞,则希望完全破灭,报出deadlock
&nbsp;&nbsp;&nbsp;&nbsp;go&nbsp;func()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//子协程2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(&quot;22222----lock&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.Sleep(3&nbsp;*&nbsp;time.Second)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(&quot;2&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;-ch
&nbsp;&nbsp;&nbsp;&nbsp;}()
&nbsp;&nbsp;&nbsp;&nbsp;ch&nbsp;&lt;-&nbsp;struct{}{}
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;close(ch)
}</pre>

杰克工作室 发表于 2023-7-26 17:48

如果将1楼chan对应代码改为sync.WaitGroup,可以得到完美答案:
<pre>
package main
import (
&nbsp;&nbsp; &nbsp;&quot;fmt&quot;
&nbsp;&nbsp; &nbsp;&quot;sync&quot;
&nbsp;&nbsp; &nbsp;&quot;time&quot;
)
func main() {
&nbsp;&nbsp; &nbsp;wg := sync.WaitGroup{}
&nbsp;&nbsp; &nbsp;wg.Add(1)
&nbsp;&nbsp; &nbsp;go func() { //子协程1
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;fmt.Println(&quot;1111----lock&quot;)
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;time.Sleep(2 * time.Second) //sleep一个很长的时间
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;wg.Done()
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;fmt.Println(&quot;1&quot;)

&nbsp;&nbsp; &nbsp;}()

&nbsp;&nbsp; &nbsp;wg.Add(1) &nbsp; //由于子协程1已经启动,寄希望于子协程1帮自己解除阻塞,所以会一直等子协程1执行结束。如果子协程1执行结束后没帮自己解除阻塞,则希望完全破灭,报出deadlock
&nbsp;&nbsp; &nbsp;go func() { //子协程2
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;fmt.Println(&quot;22222----lock&quot;)
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;time.Sleep(3 * time.Second)
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;fmt.Println(&quot;2&quot;)
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;wg.Done()
&nbsp;&nbsp; &nbsp;}()
&nbsp;&nbsp; &nbsp;wg.Wait()
}
运行结果:
22222----lock
1111----lock
1
2</pre>
页: [1]
查看完整版本: 为啥使用chan时,输出结果不固定