为啥使用chan时,输出结果不固定
<p><img alt="chan为啥运行的结果不固定.jpg" src="data/attachment/forum/202303/01/6758f1082383121da231917cdf6e54a6.jpg" title="16617564501661756450_3997.jpg" /></p><p> </p>
<p>请认真回答以下问题:</p>
<p>1、为啥输出结果不固定?会出现死锁吗?会一直运行下去吗?</p>
<p>2、第10行代码打开后,请写出输出结果?</p>
<p>3、将第25行代码注释后,打开第10行代码,程序可以输出什么?为什么?</p>
<p>4、第10行代码打开,将第14行代码与第15行代码互换后,会影响结果输出吗?那输出结果会是什么呢?</p>
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结果。 https://zhuanlan.zhihu.com/p/397669964
https://zhuanlan.zhihu.com/p/385371995
以上为代码原型,主要用来了解goroute。 补充1楼,源代码:
<pre>
package main
import (
"time"
"fmt"
)
func main() {
ch := make(chan struct{}, 1)
// ch <- struct{}{} //有1个缓冲可以用,无需阻塞,可以立即执行
go func() { //子协程1
fmt.Println("1111----lock")
time.Sleep(2 * time.Second) //sleep一个很长的时间
<-ch
fmt.Println("1")
}()
ch <- struct{}{} //由于子协程1已经启动,寄希望于子协程1帮自己解除阻塞,所以会一直等子协程1执行结束。如果子协程1执行结束后没帮自己解除阻塞,则希望完全破灭,报出deadlock
go func() { //子协程2
fmt.Println("22222----lock")
time.Sleep(3 * time.Second)
fmt.Println("2")
<-ch
}()
ch <- struct{}{}
// close(ch)
}</pre>
如果将1楼chan对应代码改为sync.WaitGroup,可以得到完美答案:
<pre>
package main
import (
"fmt"
"sync"
"time"
)
func main() {
wg := sync.WaitGroup{}
wg.Add(1)
go func() { //子协程1
fmt.Println("1111----lock")
time.Sleep(2 * time.Second) //sleep一个很长的时间
wg.Done()
fmt.Println("1")
}()
wg.Add(1) //由于子协程1已经启动,寄希望于子协程1帮自己解除阻塞,所以会一直等子协程1执行结束。如果子协程1执行结束后没帮自己解除阻塞,则希望完全破灭,报出deadlock
go func() { //子协程2
fmt.Println("22222----lock")
time.Sleep(3 * time.Second)
fmt.Println("2")
wg.Done()
}()
wg.Wait()
}
运行结果:
22222----lock
1111----lock
1
2</pre>
页:
[1]