Go 语言自带的 goroutine 特性会让我们需要在某些时候由 main 函数启动一些协程之后就无限阻塞, 让别的协程处理问题. 以下是一些方式:
死循环法
for {;}
使用这种方式会让你的程序 随机暴毙, 无法 Debug 找到问题出在哪儿.
原因: go 语言中的 goroutine 并不是线程, 当且仅当遇到系统调用和io操作等时候会主动让出自己的时间片等待外部数据. 但是, 当程序运行死循环的时候 并没有任何io操作, 不会主动让出自己的时间片. 又由于线程调度的原因, 程序会在一个随机时间进入死循环执行, 导致整个程序所有协程全部卡死. 不仅如此, 由于系统会在别的协程进行io操作的时候进行携程调度, 因此 表面上观察到的现象是别的携程在进行io操作的时候堵死整个程序 , 几乎无法找到bug在哪儿
死循环让出时间片法
for { runtime.Gosched()}
死循环执行 runtime.Gosched() 这一函数, 执行这个函数会让出当前协程的时间片, 稍后再回到此协程. 不会出bug, 但是效率偏低. (因为仍然在不断地切换到这个携程.)
死循环Sleep法
for { time.Sleep(Time.Hour)}
同上, 仍然有轻微的(但完全可以忽略)效率问题, 但是这样实现十分不优雅.
阻塞的读取空数据法:
blockChan := make(chan int)a := <- blockChan
这种方法创建一个不会有数据的 Channel, 并试图从中读取数据. 因为永远读不到数据, 因此会堵塞这个协程.
无效率问题, 但是实现仍然不优雅.
WaitGroup法:
w := sync.WaitGroup{}wg.Add(1)wg.Wait()
创建一个WaitGroup, 调用 wait 方法无限等待. 无效率问题, 但是仍然不优雅(要写三行).
Select法:
select{}
select被用于同步或异步的从Channel中读取数据. 因为这里没有指定任何Channel, 同时没有default来进行异步读取, 程序会阻塞的试图从没有channel中读取数据.
没有创建任何变量, 0内存开销, 同时调度器也再也不会调度这个协程, 也同样没有性能开销.
(关键是只要一行)
特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。
- 赞助本站
- 微信扫一扫
-
- 加入Q群
- QQ扫一扫
-
评论