找回密码
 立即注册
搜索
查看: 508|回复: 4

[go基础] 为啥使用chan时,输出结果不固定

  [复制链接]
发表于 2023-3-1 11:01 | 显示全部楼层 |阅读模式

chan为啥运行的结果不固定.jpg

 

请认真回答以下问题:

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

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

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

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
 楼主| 发表于 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楼,源代码:
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)
}
 楼主| 发表于 2023-7-26 17:48 | 显示全部楼层
如果将1楼chan对应代码改为sync.WaitGroup,可以得到完美答案:
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
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|学习笔记

GMT+8, 2024-12-21 19:54 , Processed in 0.029795 second(s), 13 queries , APCu On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表