2

私は C でのマルチスレッドが初めてで、この質問がありました。次のコードを書きました。

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

pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
pthread_attr_t attr;

void* test(void *a)
{
    int i=*((int *)a);
    printf("The thread %d has started.\n",i);
    pthread_mutex_lock(&m);
    sleep(1);
    printf("The thread %d has finished.\n",i);
    pthread_mutex_unlock(&m);
    pthread_exit(NULL);

}

int main()
{
    int i=0;
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
    pthread_t thread[5];

    for (i=0;i<5;i++)
        pthread_create(&thread[i],&attr,test,&i);

    for (i=0;i<5;i++)
        pthread_join(thread[i],NULL);
    return 0;
}

次のような値が得られるのはなぜですか。

The thread 0 has started.
The thread 0 has started.
The thread 5 has started.
The thread 5 has started.
The thread 0 has started.
The thread 0 has finished.
The thread 0 has finished.
The thread 5 has finished.
The thread 5 has finished.
The thread 0 has finished.

また

The thread 1 has started.
The thread 2 has started.
The thread 5 has started.
The thread 4 has started.
The thread 0 has started.
The thread 1 has finished.
The thread 2 has finished.
The thread 5 has finished.
The thread 4 has finished.
The thread 0 has finished.

あるいは:

The thread 0 has started.
The thread 0 has started.
The thread 0 has started.
The thread 0 has started.
The thread 0 has started.
The thread 0 has finished.
The thread 0 has finished.
The thread 0 has finished.
The thread 0 has finished.
The thread 0 has finished.

など、私が得ると思ったとき:

The thread 0 has started.
The thread 1 has started.
The thread 2 has started.
The thread 3 has started.
The thread 4 has started.
The thread 0 has finished.
The thread 1 has finished.
The thread 2 has finished.
The thread 3 has finished.
The thread 4 has finished.

usleep(10)後に入れたときにのみ、thread_create「通常の」値が得られます。

Unix の Code::Blocks でこのコードをコンパイルして実行しました。

4

2 に答える 2

5

変化する変数のアドレスを渡しているfor( i) ので、スケジューラに翻弄されます。コピーを渡すだけです。安価で完全にコーシャではない方法として:

pthread_create(&thread[i],&attr,test, (void*)i);

/* ... */

int i = (int)a;
于 2013-01-02T21:46:25.883 に答える
2

iのアドレスをパラメーターとしてスレッドに渡していることに注意してください。

pthread_create(&thread[i],&attr,test,&i);

これは、すべてのスレッドが同じ変数iを読み取って、どのスレッドであるかを判断することを意味します。つまり、5 つのスレッドすべてが同じ変数を調べて、スレッド番号を決定します。したがって、ループ内で の値がi増加するとfor、すべてのスレッドは、 の新しい値を使用するように変更されたスレッド番号を認識しますi。これが、スレッド番号として 5 が表示されることがある理由であり、番号をスキップしたり、重複が多すぎることがよくあるという事実も説明しています。

これを修正するには、各スレッドに独自の のコピーを与える必要がありますi。たとえば、次のようなことができます。

int* myI = malloc(sizeof(int));
*myI = i;
pthread_create(&thread[i], &attr, test, myI);

そして、終了する前にスレッドにポインターを解放させます。

void* test(void *a)
{
    int i=*((int *)a);
    printf("The thread %d has started.\n",i);
    pthread_mutex_lock(&m);
    sleep(1);
    printf("The thread %d has finished.\n",i);
    pthread_mutex_unlock(&m);
    pthread_exit(NULL);
    free(a);
}

または、 a にキャストiしてvoid*それを渡すこともできます。

pthread_create(&thread[i],&attr,test, (void*)i);

これを行うと、スレッドは引数をintではなく に直接キャストすることになりint*ます。

void* test(void *a)
{
    int i = (int)a;
    printf("The thread %d has started.\n",i);
    pthread_mutex_lock(&m);
    sleep(1);
    printf("The thread %d has finished.\n",i);
    pthread_mutex_unlock(&m);
    pthread_exit(NULL);
}

お役に立てれば!

于 2013-01-02T21:48:10.997 に答える