我有一个用 pthreads 编写的多线程 c 程序。我想知道我所做的是否正确。目前,该程序似乎在没有优化时运行。但是当我使用优化时,它失败了。我试图找出原因。
我想知道我使用的基本多线程同步是否正确。这是一个仅包含相关部分的简短版本。请让我知道这是否是多线程的正确方法。
它的工作方式:每个工人都有许多工作要做。工作线程首先启动。然后他们等到主线程分配给他们一个工作。他们完成了工作,关闭了主线程并再次返回等待。
主线程将作业分配给 N 个工作人员并通知他们开始。然后它等待它们完成并恢复正常工作。
每个工作线程都有一个名为 workerCtx 的上下文变量。这存储了工作人员所需的所有相关信息以及互斥锁和 cond 变量。
主线程也有一个互斥锁和一个 cond 变量。
父级也有一个名为 threadCompletionCount 的变量。在分配工作之前,该变量最初为 0。一旦每个工作线程完成,它将在互斥锁的保护下将该变量加一并向父线程发出信号。当这个变量等于worker的数量时,父线程就会知道所有的worker都已经完成了。
这是workerCtx的简短版本
typedef enum {INITIALIZE = 0 , WAIT = 1, WORK1 = 2, WORK2 =3, DIE = 4} worktype_t;
typedef struct workerCtx_t
{
int id;
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_mutex_t * parentMutex;
pthread_cond_t * parentCond;
int * parentThreadCompletionCount;
worktype_t workType;
//Other application specific variables follow.
}workerCtx_t;
这里 mutex 和 cond 指的是特定于该线程的本地 mutex 和 cond 变量。parentMutex 和 parentCond 是引用父级变量的变量。所有线程都指向相同的 parentMutex 和 parentCond。
以下是主线程的工作方式:
void waitForWorkerCompletion()
{
int status;
status = pthread_mutex_lock(&mutex);
while (threadCompletionCount < NUM_WORKERS)
{
status = pthread_cond_wait(&cond, &mutex);
}
status = pthread_mutex_unlock(&mutex);
status = pthread_mutex_lock(&mutex);
threadCompletionCount = 0;
status = pthread_mutex_unlock(&mutex);
}
void assignWorkToWorker(worktype_t workType)
{
for(int i=0; i<NUM_WORKERS; i++)
{
pthread_mutex_lock(&(workerCtxs[i]->mutex) );
workerCtxs[i]->workType = workType;
pthread_cond_signal(&(workerCtxs[i]->cond) );
pthread_mutex_unlock(&(workerCtxs[i]->mutex));
}
waitForWorkerCompletion();
}
void setup
{
for(int i=0; i<NUM_WORKERS; i++)
{
workerCtxs[i]->id = i;
workerCtxs[i]->workType = WAIT;
assert( pthread_mutex_init(&(workerCtxs[i]->mutex), NULL) == 0) ;
assert( pthread_cond_init(&(workerCtxs[i]->cond), NULL) == 0);
workerCtxs[i]->parentMutex = &mutex;
workerCtxs[i]->parentCond = &cond;
workerCtxs[i]->parentThreadCompletionCount = &threadCompletionCount;
pthread_create (&(workers[i]), NULL, workerMain, (workerCtxs[i]) );
}
}
int main()
{
setup()
For each work (workType_t workType) that comes up
assignWorkToWorker(workType);
}
以下是每个工人的工作:
void signalCompletion(workerCtx_t * ctx)
{
pthread_mutex_lock(&ctx->mutex);
ctx->workType = WAIT;
pthread_mutex_unlock(&ctx->mutex);
int rc = pthread_mutex_lock(ctx->parentMutex);
*(ctx->parentThreadCompletionCount) = *(ctx->parentThreadCompletionCount) + 1;
pthread_cond_signal(ctx->parentCond);
rc = pthread_mutex_unlock(ctx->parentMutex);
}
void * workerMain(void * arg)
{
workerCtx_t * ctx = (workerCtx_t *) arg;
while(1)
{
pthread_mutex_lock(&ctx->mutex);
while(ctx->workType == WAIT);
{
int status = pthread_cond_wait(&ctx->cond, &ctx->mutex);
}
pthread_mutex_unlock(&ctx->mutex);
if(ctx->workType == INITIALIZE)
{
init(ctx);
signalCompletion(ctx);
}
else if(ctx->workType == WORK1)
{
doWork1(ctx);
signalCompletion(ctx);
}
else if(ctx->workType == WORK2)
{
doWork2(ctx);
signalCompletion(ctx);
}
else if(ctx->workType == DIE)
{
signalCompletion(ctx);
break;
}
}
return NULL;
}
我希望我已经使这很容易理解,并从发布的代码中删除了所有面向应用程序的细节。此代码仅处理多线程部分。现在程序挂起。当我使用 gdb 时,它告诉我它正在waitForWorkerCompletion()方法中等待。
这个多线程模型正确吗?