timeout context 父子超时顺序问题


写在前面

如果父子context都有超时控制,哪个先执行呢?

示例

func main() {
	begin := time.Now()
	parentCtxTimeout := 4 // 父级 context 超时时间
	childCtxTimeout := 2  // 子级 context 超时时间
	// 创建一个父级 context
	parentCtx, parentCancel := context.WithTimeout(context.Background(), time.Duration(parentCtxTimeout)*time.Second)
	defer parentCancel()
	// 创建一个子级 context
	childCtx, childCancel := context.WithTimeout(parentCtx, time.Duration(childCtxTimeout)*time.Second)
	defer childCancel()
	// 在子级 context 中执行一个耗时操作
	go func(ctx context.Context) {
		select {
		case <-ctx.Done():
			fmt.Println("子级 context 超时", time.Since(begin).Seconds())
		}
	}(childCtx)
	// 在父级 context 中执行一个耗时操作
	go func(ctx context.Context) {
		select {
		case <-ctx.Done():
			fmt.Println("父级 context 超时", time.Since(begin).Seconds())
		}
	}(parentCtx)

	// 等待一段时间,模拟耗时操作
	time.Sleep(6 * time.Second)
	fmt.Println("main end", time.Since(begin).Seconds())
}

当父级超时时间是4s,子级是2s,结果如下

子级 context 超时 2.000300793
父级 context 超时 4.000081723
main end 6.000560688

当父级超时时间是2s,子级是4s,结果如下

父级 context 超时 2.000386216
子级 context 超时 2.000359559
main end 6.000680899

这里的父子一起超时,先后顺序是随机的。

当父级超时时间是2s,子级是2s,结果如下

子级 context 超时 2.001217233
父级 context 超时 2.001284261
main end 6.001142147

结论

  • 父级 context 超时时间>子级 context 超时时间,子级 context先超时,父级context后超时
  • 父级 context 超时时间<子级 context 超时时间,子级 context随着父级 context超时而超时,没有先后顺序
  • 父级 context 超时时间=子级 context 超时时间,子级 context随着父级 context超时而超时,而且子级先超时,父级后超时


文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
  目录