首页 > 解决方案 > 工作线程,具有特定“颜色”的作业,每种颜色只能运行一个作业,我需要什么同步原语?

问题描述

我有 N 个工作线程和一个作业队列。当工作线程空闲时,它会从队列中挑选一个作业并开始运行它。到目前为止,很容易。

然而,我的工作有一个属性,我称之为“颜色”。决不能同时运行两个相同颜色的作业。

例如,假设有 2 个线程,一个正在运行红色作业,另一个处于空闲状态。空闲线程查看队列,但它不能选择红色作业(因为如果这样做,将有两个红色作业正在运行,这是不允许的)。如果队列中有一个蓝色作业,它可以运行它。如果队列中只有红色作业,则空闲线程必须等到另一个线程完成。然后两个线程都处于空闲状态,它们必须选择不同颜色的作业来运行,如果到那时队列中仍然只有红色作业,则必须保持空闲状态。

我的问题是我应该在这里使用什么同步原语。我考虑将队列分组为颜色,并且可以将互斥锁附加到每个颜色组,但后来我被困在如何使用这些互斥锁上。(实际的程序是使用 pthreads 用 OCaml 编写的,因此它可以访问通常的 pthread 原语和构建在 pthreads 之上的原语)。

这听起来像是一个相当不寻常的案例,但它与现实世界的问题有关:我正在编写一个依赖运行程序(想想:“make”)。如果两个配方以相同的输出文件(“颜色”)为目标,则它绝不能并行运行两个配方(“作业”)。

标签: multithreadingpthreads

解决方案


有一些“明显”的解决方案。

  1. 您可以有一个“红色”线程和一个“蓝色”线程,分别为“红色”和“蓝色”队列提供服务。由于您永远不想拥有多个正在进行的“红色”工作,因此拥有线程池不会给您带来任何好处。

  2. 如果由于某种原因您仍想在线程池上多路复用“红色”作业,您仍然可以使用单独的“红色”和“蓝色”队列,以及指示相应颜色作业是否正在进行的布尔标志。然后一个空闲线程将遍历所有非空队列并选择第一个具有in_progress == false.

  3. 您可以将单个队列与一组布尔标志组合在一起。现在空闲线程将遍历队列,直到找到一个工作in_progress[color] == false并选择它。


推荐阅读