我正在寻找一种算法来解决以下问题:
两个核心都试图使用多个资源池中的一个资源。一般来说,他们不会同时使用相同的资源,但当然可能会。仅在这种情况下,一个核心应该等待另一个核心完成。否则他们可以/应该并行地完成他们的工作。
所以核心会做类似的事情:
lock(n);
"do something with resource n"
unlock(n);
其中n是资源的数量,资源有很多。
我已经实现了一些似乎有效的代码,但我真的不想重新发明轮子,而且我担心我的代码包含一些奇怪的竞争条件,这些条件会在将来的某个地方出现。有谁知道是否有一个标准算法?
最诚挚的问候,
阿诺
最佳答案
从表面上看,您似乎在问两件事:
- 这是一种常见模式吗?
- 我做得正确吗?
要解决#1,是的,这很常见,但据我所知,没有标准 API 或算法可以用 C 语言执行此操作,尤其是当您的资源是动态分配的时。如果您可以预先分配资源,并且始终使用整数访问它们,则可以简单地执行以下操作:
#define N_RESOURCES 1024
#define lock_resource(n) pthread_mutex_lock(&(resources[(n)].mtx))
#define unlock_resource(n) pthread_mutex_unlock(&(resources[(n)].mtx))
struct resource *resources = calloc(N_RESOURCES, sizeof (*resources));
如果struct resource *
不是指向您的不透明指针,并且它们是动态分配的,您始终可以这样做:
#define lock_resource(r) pthread_mutex_lock(&((r)->mtx))
#define unlock_resource(r) pthread_mutex_unlock(&((r)->mtx))
如果是不透明指针:
struct locked_resource {
struct resource *r;
pthread_mutex_t mtx;
}
并使用上面的锁定策略。
如果资源是动态的,并且需要在分配时初始化锁,并且无法预分配它们,但可以设置处理的资源数量上限,则可以使用锁 vector 并维护一个空闲列表。您还可以使用 sparse array 。当然,如果资源也是并发分配的,那么在分配/销毁资源时,您必须保护您的 vector/空闲列表/锁池。
这可能是您试图避免的情况,此时可能值得问一下您是否可以在排队生产者和消费者方面更好地识别您的工作模型并使用 a non-blocking data structure相反。
对于第二个问题,很难说,因为你还没有真正证明你实际上在做什么。有鉴于此,我有点怀疑这就是您正在寻找的答案。特别是,您的资源似乎可能是动态分配的,并且它们可能在某个时刻消失(也许使 lock(n)
导致未定义的行为)。
如果您可以提供更好的示例,或者展示您用来解决此问题的代码,我(或某人)也许能够更好地回答您的问题。
关于c - 多种资源的细粒度锁定算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28317104/