Go 语言中让某个协程无限堵塞的几种方式.

幸运草
幸运草
幸运草
878
文章
3
评论
2020年4月12日22:11:45 评论 235

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日内与变化吧联系。

幸运草
Go语言接口规则 前端框架

Go语言接口规则

Go语言接口规则 接口是一个或多个方法签名的集合。任何类型的方法集中只要拥有该接口对应的全部方法签名。就表示它 "实现" 了该接口,无须在该类型上显式声明实现了哪个接口。对应方法,是指有相同名称、参数...
Go语言中处理 HTTP 服务器 前端框架

Go语言中处理 HTTP 服务器

1 概述 包 net/http 提供了HTTP服务器端和客户端的实现。本文说明关于服务器端的部分。 快速开始: package main import (   "log"   "net/http" )...