在C中为线程池分配唯一的源



我使用这个库来创建pthread的排队池。线程由操作系统决定,但我们知道,只要队列已满,我们总是有4个作业(在下面的情况下(同时运行。

如果每个作业使用4个可用来源中的一个来源,我想保证同时使用所有4个来源。避免一个源使用两次,而另一个源一次不使用。

我想出了这个主意,用一个数组来跟踪使用过的源

#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
#include <unistd.h>
#include "thpool.h"
int sources[4] = {0}; // 0 Source is available 1 Source is occupied
void task(void *arg)
{
int source;
for (int i = 0; i < 4; i++)
{
if (sources[i] == 0)
{
sources[i] = 1; // Occupying the source
source = i; // Assining the source
break;
}
}
sleep(1);
printf("Thread %u working on %d with source %dn", (int)pthread_self(), (int)arg, source);
sources[source] = 0; // Making the source available again
}
int main()
{
puts("Making threadpool with 4 threads");
threadpool thpool = thpool_init(4);
puts("Adding 40 tasks to threadpool");
int i;
for (i = 0; i < 40; i++)
{
thpool_add_work(thpool, task, (void *)(uintptr_t)i);
};
thpool_wait(thpool);
puts("Killing threadpool");
thpool_destroy(thpool);
return 0;
}

这在基本测试中运行良好,但我不确定可靠性,因为我们没有锁定更新sources数组的过程。

在我看来,你似乎在重新发明轮子,但不幸的是,方法不对。POSIX线程API已经具有您正在寻找的特性:互斥对象。只需定义4个互斥,并使用它们来锁定/解锁资源。

pthread_mutex_t locks[4] = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER
};
void task(void *arg) {
pthread_mutex_t *lock;
for (int i = 0; i < 4; i++) {
lock = &locks[i];
if (!pthread_mutex_trylock(lock))
break;
}
// Work ...
pthread_mutex_unlock(lock);
}

注意:只有当最多有4个线程同时运行时,上述代码才有效(您提到您使用的库强制执行此规则,所以这应该没问题(。如果您有更多,那么从第5个线程开始,上面的代码将无法锁定任何互斥体,然后将尝试解锁被另一个线程锁定的互斥体,这非常糟糕。在这种情况下,您需要将for循环封装为while (1),或者提出一个稍微复杂一点的不同解决方案,例如使用条件或信号量。

最新更新