【问题标题】:Execute jobs concurrently in sequential order按顺序同时执行作业
【发布时间】:2019-09-07 20:40:00
【问题描述】:

“什么?”你问,“这个标题没有任何意义。”

考虑以下几点: 不同 id 的作业可以异步处理,但相同 id 的作业应该同步处理,并从队列中按顺序处理。

我当前的实现创建了一个 go 例程来处理每个特定 id 的作业,看起来像这样:

func FanOut() chan<- *Job {
    channel := make(chan *Job)
    routines = make(map[string]chan<- *Job)
    go func() {
        for j := range channel {
            r, found := routines[j.id]
            if !found {
                r = Routine()
                routines[j.id] = r
            }
            r <- j
        }
    }()
    return channel
}

这似乎运行良好(在当前测试中),但创建数千个 go 例程可能不是最好的方法?此外,除非使用缓冲通道,否则扇出代码块。

我正在考虑使用 sync.Mutex 的集合,而不是 go 例程的集合(上图)。这个想法是有一个 go 例程池,它必须首先在对应于作业 id 的互斥锁上建立一个锁。

是否有任何现有的 Go 模式适合处理这些要求?

有更好的方法吗?

【问题讨论】:

  • 真的没有“太多的 goroutines”。在内部,Google 运行着产生数百万个 goroutine 的服务。它们的设计是轻量级的。
  • 鉴于 Go 例程的轻量级特性,您会说这里的设计是合理的吗?
  • 我没有足够的信息可以这么说,但根据所提供的信息,我不会立即称其为不合理。除非您测量并发现问题,否则我会假设没有问题。
  • 感谢您的 cmets!

标签: go concurrency sequential


【解决方案1】:

为每个 ID 创建一个频道 - 可能是一片频道或一张地图(按 ID 索引)。每个通道都有一个按顺序处理该 ID 的作业的 go-routine。很简单。

我不会担心创建太多 go-routines。而且我不会使用互斥锁 - 如果不使用通道和 go-routines 进行太多细节,那么每个作业一次只能由一个 go-routines 处理,并避免数据竞争的可能性。

顺便说一句,我只添加了这个作为答案,因为我不允许添加 cmets(还没有?)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 2019-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多