MST

星途 面试题库

面试题:Go任务队列中context取消机制的优化

在Go使用context管理任务队列上下文依赖时,假设任务队列中有大量任务,如何优化context的取消机制,以确保所有相关任务能及时、高效地被取消,同时避免资源浪费和潜在的竞态条件,请详细说明思路和代码实现要点。
17.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

思路

  1. 分层设计:为不同层级的任务组创建不同的context,当上层context取消时,下层所有相关任务的context也能相应取消。例如,将任务按功能模块划分为不同组,每个组有独立的context,由一个总的context管理这些组的context。
  2. 使用select语句:在任务执行函数中,通过select语句监听context的取消信号。这样任务可以在接收到取消信号时,及时停止执行。
  3. 减少不必要的等待:避免在任务中出现长时间阻塞且无法响应取消信号的操作。若存在如网络请求等可能阻塞的操作,使用支持取消的接口(如http.Request中设置context)。
  4. 避免竞态条件:使用sync.Mutexsync.RWMutex来保护共享资源,确保在context取消过程中,对共享资源的访问是安全的。同时,合理使用channel进行任务间的通信,避免多个任务同时修改同一数据。

代码实现要点

  1. 创建context
ctx, cancel := context.WithCancel(context.Background())

如果任务有执行时间限制,可使用context.WithTimeoutcontext.WithDeadline。 2. 任务执行函数

func task(ctx context.Context, taskID int) {
    for {
        select {
        case <-ctx.Done():
            // 清理资源,如关闭文件、数据库连接等
            return
        default:
            // 执行任务逻辑
            println("Task", taskID, "is running")
        }
    }
}
  1. 启动任务
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
    wg.Add(1)
    go func(id int) {
        defer wg.Done()
        task(ctx, id)
    }(i)
}
  1. 取消任务
// 当满足某个条件时取消任务
cancel()
wg.Wait()
  1. 保护共享资源: 若任务间存在共享资源,例如一个共享的计数器:
var counter int
var mu sync.Mutex
func task(ctx context.Context, taskID int) {
    for {
        select {
        case <-ctx.Done():
            return
        default:
            mu.Lock()
            counter++
            mu.Unlock()
        }
    }
}