pthreads で書かれたマルチスレッドの C プログラムがあります。自分のしていることが正しいかどうか知りたい。現在、プログラムは最適化がない場合に実行されるようです。しかし、最適化を使用すると失敗します。私はその理由を理解しようとしています。
私が使用している基本的なマルチスレッド同期が正しいかどうかを知りたいです。関連する部分のみを含む短いバージョンを次に示します。これがマルチスレッドの正しい方法かどうか教えてください。
仕組み: 各労働者には、やるべき仕事がたくさんあります。ワーカー スレッドが最初に開始されます。次に、メイン スレッドによってジョブが割り当てられるまで待機します。彼らは仕事を完了し、メインスレッドを親密にし、再び待機に戻ります.
メイン スレッドは N 個のワーカーにジョブを割り当て、開始するように信号を送ります。次に、それらの完了を待って、通常の作業を再開します。
各ワーカー スレッドには、workerCtx という名前のコンテキスト変数があります。これにより、ワーカーが必要とするすべての関連情報と、mutex および cond 変数が保存されます。
メインスレッドにもミューテックスと cond 変数があります。
また、親には、threadCompletionCount という変数があります。作業を割り当てる前の初期状態では、この変数は 0 です。各ワーカー スレッドが完了すると、ミューテックスの保護下でこの変数を 1 つ増やし、親スレッドに通知します。親スレッドは、この変数がワーカーの数と等しくなると、すべてのワーカーが完了したことを認識します。
これは 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()メソッドで待機中であることがわかります。
このマルチスレッド モデルは正しいですか??