Concurrency 对对象组的并发访问

Concurrency 对对象组的并发访问,concurrency,scheduled-tasks,scheduling,mutual-exclusion,Concurrency,Scheduled Tasks,Scheduling,Mutual Exclusion,我正在尝试开发一个由线程池组成的应用程序,使用工作窃取算法来并发执行任务 这些任务 访问预定义的对象集 在实际运行之前,必须“原子地”获取其访问的所有对象的读/写权限 完成后(并保证最终完成),释放他们获取的对象 解决此问题的一种可能方法是让每个线程一次执行一个任务,然后尝试使用预定义的顺序锁定每个对象。如果至少有一个失败,请释放所有锁,然后继续执行另一个任务 然而,这种方法增加了具有大对象依赖性的任务的饥饿概率,甚至可能导致活锁 在最大化并发性的同时,是否还有其他方法可以获取一组锁?(没有

我正在尝试开发一个由线程池组成的应用程序,使用工作窃取算法来并发执行任务

这些任务

  • 访问预定义的对象集
  • 在实际运行之前,必须“原子地”获取其访问的所有对象的读/写权限
  • 完成后(并保证最终完成),释放他们获取的对象
解决此问题的一种可能方法是让每个线程一次执行一个任务,然后尝试使用预定义的顺序锁定每个对象。如果至少有一个失败,请释放所有锁,然后继续执行另一个任务

然而,这种方法增加了具有大对象依赖性的任务的饥饿概率,甚至可能导致活锁

在最大化并发性的同时,是否还有其他方法可以获取一组锁?(没有全局锁)或者以不再需要的方式更改系统? 如果是的话,有关于它的好文章吗


ps:正如蒂顿所回答的,这是“哲学家进餐”问题的一般化版本。我正在寻找非集中式的解决方案,特别是在高负载(添加和删除任务)下运行良好的算法。

如果一个任务试图锁定对象,但在某个点失败,那么另一个任务可能无法锁定对象,因为第一个任务当时拥有它

我想我会在最初尝试获取锁时使用全局锁,也可能在最终释放它们时使用全局锁


当一个简单的解决方案在实践中被证明是不够的时候,我会担心最大的并发性。

您的问题被称为。您可以在这个关键字下找到所需的任何数量的文献:-)。

对资源进行排序是一种有效的方法。我想到的另一个简单的方法是引入一个共享仲裁器,该仲裁器保存有关资源可用性的信息。任务将通过仲裁器在单个原子步骤“acquire(r1,r2,…,rn)”中锁定所需的所有资源,并使用“release(r1,r2,…,rn)”类似地释放它们

如果可以满足“获取”请求A,则仲裁员将确保在A将其释放之前,其他任务不能获取A所持有的任何资源

仲裁员可以使用几种策略来满足传入请求:

  • 拒绝无法立即满足的请求-任务必须重新尝试。这为活锁和饥饿打开了大门
  • 将所有传入的请求保持在队列中,并以FIFO方式为它们提供服务,因为头部请求所需的资源可用
  • 将所有未满足的请求保留在一个列表中(不阻塞它们所需的资源),并在每次释放某些资源时对它们进行迭代(可能对较旧的请求具有优先级),以找到可以满足的请求

  • 这是一个有效的解决办法。但是,由于只有一个仲裁器,所有任务都必须在仲裁器的锁队列中等待,这会导致争用。此外,验证可能并发任务的线程是在单个线程中执行的,这将限制最大并发性。现在,考虑到您非常有效的评论,我可能会设计这样一个仲裁器系统,使仲裁器不会处理线程,而是处理任务。与阻塞线程相比,在等待资源时阻塞任务(工作)对吞吐量的影响可能要小得多。只对任务的资源进行分类,(续)仲裁员将逐步读取任务,分配它们所需的资源,并将那些获得所有资源的资源放入线程池进行处理。如果任务需要一些时间来执行,单线程仲裁器可能不会成为瓶颈。我想这一切都取决于任务大小。正如我对系统的设想,这些任务将非常小,可能在数千个CPU周期的顺序中。这就是为什么我要求一个分散的算法。也许我会同时实现这两种方法,看看哪一种效果更好。我现在想起来了!最准确地说,这是一个“广义进餐哲学家”问题,没有2个叉子/哲学家的限制。理论上,这些任务执行得非常快,线程大部分时间都在试图找出要运行的任务。使用全局锁会使问题变得更糟,因为决策过程将由单个线程执行,而不是分布式执行。