golang:context

2023-09-18 13:55:32

context作用

goroutine的退出机制

多个goroutine都是平行的被调度的,多个goroutine如何协调工作涉及通信、同步、通知和退出

  • 通信:goroutine之间的通信同步chan通道

  • 同步:不带缓冲的chan提供了一个天然的同步等待机制。通过WaitGroup也可以为多个goroutine提供同步等待机制

  • 通知:这个通知和上面通信的数据不一样,通知通常不是业务数据,而是管理、控制流数据。要处理这个也好办,在输入端绑定两个chan,一个用于业务流数据,另一个用于异常通知数据,然后通过 select 收敛进行处理。这个方案可以解决简的问题,但不是一个通用的解决方案。

  • 退出:goroutine 之间没有父子关系,如何通知 goroutine 退出?可以通过增加一个个单独的通道,借助通道和 select 的广播机制( close channel to broadcast)实现退出

通知退出机制:

  • 读取已经关闭的通道不会引起阻塞,也不会导致panic,而是立即返回该通道存储类型的零值

  • 关闭select监听的某个通道能使select立即感知这种通知,然后进行相应的处理,即所谓的退出通知机制

contet库的设计目的就是跟踪 goroutine调用树,并在这些goroutine 调用树中递通知和元数据

  • 退出通知机制:通知可以传递给整个 goroutine调用树上的每一个goroutine

  • 传递数据:数据可传递给整个goroutine 调用树上的每一个goroutine

使用

var wg sync.WaitGroup
func main() {
   background := context.Background()
   //通过cancel进行控制
   /*cancelctx, cancelFunc := context.WithCancel(background)
   wg.Add(2)
   go jiankong1(cancelctx)
   time.Sleep(time.Second * 2)
   println("并不是因为主协程退出,而导致另一个协程退出,而是通过cancel方法通知另一个协程进行退出!")
   cancelFunc()
   wg.Wait()
   println("完成退出")*/

   //通过deadline进行控制,也可以通过返回的cancelFunc手动进行控制
   /*deadline, _ := context.WithDeadline(background, time.Now().Add(time.Second*2))
   go deadF(deadline)
   time.Sleep(time.Second * 4)
   println("结束")*/


   //通过timeout控制,也可以通过返回的cancelFunc手动进行控制   超时以后报的错和deadline控制方式一样 context deadline exceeded
   timeout, _ := context.WithTimeout(background, time.Second*2)
   go deadF(timeout)
   time.Sleep(time.Second * 4)
   println("结束")
}

func deadF(ctx context.Context) {
   for true {
      select {
      case <-ctx.Done():
         fmt.Println("只给了两秒的执行时间,时间到了,我得退出了。")
         //此处打印的错误为 context deadline exceeded
         println(ctx.Err().Error())
         return
      default:
         time.Sleep(time.Millisecond * 1000)
         fmt.Println("我正在执行...")
      }
   }
}

func jiankong1(ctx context.Context) {
   defer wg.Done()
   cancel, _ := context.WithCancel(ctx)
   go jiankong2(cancel)
   for true {
      select {
      case <-ctx.Done():
         fmt.Println("别人通知我主动退出了。在此处进行收尾工作,释放资源等")
         //此处报错为:context canceled
         fmt.Println(ctx.Err().Error())
         return
      default:
         time.Sleep(time.Millisecond * 100)
         fmt.Println("我在持续监控中...")
      }
   }
}

func jiankong2(ctx context.Context) {
   defer wg.Done()
   for true {
      select {
      case <-ctx.Done():
         fmt.Println("上级通知我主动退出了。")
         fmt.Println(ctx.Err().Error())
         return
      default:
         time.Sleep(time.Millisecond * 100)
         fmt.Println("me在持续监控中...")
      }
   }
}

Tips:

异步任务使用context注意点:

使用go func进行异步任务传入context时,要考虑context的过期时间,如果异步任务不考虑过期时间,则最好传入一个无过期时间的context,负责异步任务多或执行时间长context会过期,影响异步任务的执行。

场景:mongo批量插入数据后,将返回的Id集合传入异步任务(在异步任务中通过id查询数据),如果共用了接口设置过期时间的context,可能会导致一部分数据查询不到(context过期导致)

更多推荐

rom修改----安卓系列机型如何内置app 如何选择so文件内置

系统内置app的需求在与各工作室对接中操作单中,很多需要内置客户特定的有些app到系统里,这样方便客户刷入固件后直接调用。例如内置apk去开机引导去usb调试默认开启usb安全设置等等。那么很多app内置有不同的反应。有的可以直接内置。有的需要加so才能解决我们先来看一张图片1---直接内置方法将需要的app直接放置系

应急响应LINUX&Windows

应急响应LINUX&Windowslinux文件名说明/etc/passwd用户信息文件/etc/crontab定时任务文件/etc/anacrontab异步定时任务文件/etc/rc.d/rc.local开机启动项/var/log/btmp登录失败日志,使用last命令查看/var/log/cron定时任务执行日志/

内存管理之虚拟内存

本篇遵循内存管理->地址空间->虚拟内存的顺序描述了内存管理、地址空间与虚拟内存见的递进关系,较为详细的介绍了作为在校大学生对于虚拟内存的理解。内存管理引入RAM(内存)是计算机中非常重要的资源,由于造价的昂贵,我们家用的计算机一般是8/16G。对于如此紧俏的资源我们当然需要对它好好管理,尽力做到不浪费,高效压榨它的每

助力工业物联网,工业大数据之服务域:Shell调度测试【三十三】

文章目录知识点07:Shell调度测试知识点08:依赖调度测试知识点09:Python调度测试知识点10:Oracle与MySQL调度方法知识点11:大数据组件调度方法知识点07:Shell调度测试目标:实现Shell命令的调度测试实施需求:使用BashOperator调度执行一条Linux命令代码创建#默认的Airf

TorchLens--可视化任何PyTorch模型

0.简介PyTorch是一个深度学习框架,它使用张量(tensor)作为核心数据结构。在可视化PyTorch模型时,了解每个张量运算的意义非常重要。张量运算作为神经网络模型中的基本操作。它们用于处理输入数据、执行权重更新和生成预测结果。同时张量运算还用于计算损失函数。损失函数衡量了模型预测与真实标签之间的差异。通过使用

docker network

一、默认的三种网络模式:Bridge模式:这是Docker默认创建的网络模式。在Bridge模式下,Docker会为每个容器创建一个虚拟网络接口,并分配独立的IP地址。容器之间可以相互通信,而且可以通过端口映射让容器内部的服务可以通过主机的IP地址和端口进行访问。Host模式:在Host模式下,容器与主机共享同一个网络

代码随想录算法训练营第46天| 单词拆分,背包问题总结

139.单词拆分给你一个字符串s和一个字符串列表wordDict作为字典。请你判断是否可以利用字典中出现的单词拼接出s。注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。示例1:输入:s=“leetcode”,wordDict=[“leet”,“code”]输出:true解释:返回true因为“le

内网隧道代理技术(二十七)之 DNS隧道介绍

DNS隧道介绍DNS协议介绍域名系统(DomainNameSystem,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用TCP和UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。DNS协议是用来将域名转

Linux磁盘挂载及扩容操作

Linux磁盘扩容操作全介绍1.新增磁盘分区后挂载至新建/data目录下1.1新增磁盘打开Vmware右键需要添加磁盘的虚拟机,点击设置,选择磁盘添加即可,这里我新增了一块20G的磁盘在当前虚拟机下;fdisk-l#列出指定的外围设备的分区表状况#列出所有可用块设备的信息,而且还能显示他们之间的依赖关系#可以看到新增磁

2023:生成式AI与存储最新发展和趋势分析(下)

1.存储新发展概述近两年存储领域最大的里程碑事件应该是闪存赢得过半市场,Gartner连续几个季度的市场分析数据中也多次都确认了这一点,固态存储取代机械硬盘的趋势不可逆转。在这一大背景下,有三个新发展方向日益引起更多关注,分别是存储新介质,可计算存储(存算一体)和进一步的极致性能追求。2.介质Intel曾经用傲腾推动了

SpringMVC学习笔记——2

SpringMVC学习笔记——2一、SpringMVC的拦截器1.1、拦截器Interceptor简介1.2、拦截器快速入门1.3、拦截器执行顺序1.4、拦截器执行原理二、SpringMVC的全注解开发2.1、spring-mvc.xml中组件转化为注解形式2.1.1、消除spring-mvc.xml2.1.2、消除w

热文推荐