0

共有状態にアクセスしているときにミューテックスを保持しているコードがあるとします。ある時点で、新しいスレッドを作成する必要があると判断し、ミューテックスを保持したまま pthread_create を呼び出します。これは安全と考えられますか?

共有状態が、正常に作成された pthread の数を追跡するグローバル カウンターであり、別のスレッドがこのカウンターを使用して情報を画面にライブで表示するとします。さらに、pthreads の数が特定の最大値 (明確にするために 10 とします) よりも大きくならないようにします。

カウンターが現在 9 であるとします。カウンターをインクリメントしてから、pthread_create を呼び出す前にミューテックスを解放すると、pthread_create が失敗する可能性があり、実際に正常に作成されたよりも多くのスレッド (10) がカウンターに誤って表示されます ( 9)。

一方、最初にミューテックスを解放し、次に pthread_create を呼び出し、呼び出しが成功した場合にカウンターをインクリメントするためにミューテックスを再取得した場合、ミューテックスを解放してから pthread_create から戻るまでの間に、別のスレッドが pthread_create を呼び出した可能性もあります。カウンターをインクリメントしました(10に)。したがって、11 番目の pthread を作成したことになり、カウンターは 11 になります。

したがって、共有状態の一貫性を保証する唯一の方法は、pthread_create を呼び出している間にミューテックスを保持することです。しかし、一般に、ミューテックスを保持している間に未知のコードを呼び出すべきではないことを認識しているため、そのような場合に何ができるかわかりません。

編集:これは、この問題が発生するサンプルコードです

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *do_stuff(void *arg);

int pthreads_counter = 0;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

#define MAX_PTHREADS_COUNT 10

/* Could potentially be called from multiple threads simultaneously */
int create_thread_and_increment_counter()
{
    pthread_t thread;

    if (pthread_mutex_lock(&mtx) != 0)
        return -1;

    if (pthreads_counter >= MAX_PTHREADS_COUNT) {
        pthread_mutex_unlock(&mtx);
        return -1;
    }

    ++pthreads_counter;

    if (pthread_create(&thread, NULL, do_stuff, NULL) != 0) {
        --pthreads_counter;
        pthread_mutex_unlock(&mtx);
        return -1;
    }

    pthread_mutex_unlock(&mtx);
    return 0;
}

void *do_stuff(void *arg)
{
    /* do stuff */
    return NULL;
}

/* Created somewhere else */
void *display_thread(void *arg)
{
    while (1) {
        if (pthread_mutex_lock(&mtx) != 0)
            break;

        printf("%d\n", pthreads_counter);
        pthread_mutex_unlock(&mtx);
        usleep(1000000);
    }

    return NULL;
}
4

1 に答える 1