1

以下のプログラムの何が問題になっているのかわかりませんが、すべての言語を一度に印刷するわけではありませんが、ランダムに、より頻繁に、より少なく、一部は印刷されません

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



char *messages[] = { 
    "English: Hello World!", 
    "French: Bonjour, le monde!",
    "Spanish: Hola al mundo", 
    "Klingon: Nuq neH!",
    "German: Guten Tag, Welt!", 
    "Russian: Zdravstvytye, mir!",
    "Japan: Sekai e konnichiwa!", 
    "Latin: Orbis, te saluto!"
};
#define NUM_MESSAGES (sizeof( messages ) / sizeof( char* ))


void *PrintHello( void *messageid )
{
    pthread_t taskid;
    int *id_ptr, message_num;

    taskid = pthread_self();
    printf( "This is thread with ID %lu.\n", taskid );

    message_num = *((int *) messageid);
    printf( "%s \n", messages[message_num] );

    pthread_exit( NULL );
}

int main( int argc, char *argv[] ) 
{
    pthread_t threads[NUM_MESSAGES];
    int rc, i;


    for( i = 0; i < NUM_MESSAGES; i++ ) {
        void * argument = (void*) &i;
        rc = pthread_create( &threads[i], NULL, PrintHello, argument );
        if( rc ) {
            printf( "ERROR; return code from pthread_create() is %d\n", rc );
            exit( -1 );
        }
    }




    for( i = 0; i < NUM_MESSAGES; i++ ) {
        pthread_join( threads[i], NULL );
    }

    pthread_exit( NULL );
}

問題はどういうわけか引数ポインタに関連していると思います。別のパーツをロックしようとしましたが、成功しませんでした。

4

3 に答える 3

4

メインスレッドが変更し続けるi変数のアドレスを渡します。だからあなたはスケジューリングに翻弄されています:あなたのスレッドが実行される前に誰かが変わるでしょうか?i

代わりに、文字列を直接渡して、コードを大幅に簡略化することができます。

rc = pthread_create( &threads[i], NULL, PrintHello, messages[i]);

void *PrintHello(void *arg)
{
    char *msg = arg;
    printf("%s\n", msg);

    return NULL;
}

の実際の値をi(アドレスではなく)引数として渡す別の、より貧弱な代替手段があります。

于 2012-07-10T06:57:28.433 に答える
0

これは典型的なrace状態です。
正確には、新しいスレッドが作成された後、スレッドの実行順序によってプログラムの結果が決まります。2つの状況があります:

  1. スレッド関数PrintHelloが次のインクリメントi++とスレッドでの割り当ての前に実行されると、期待どおりの結果が出力void * argument = (void*) &i;されmainます。

  2. 新しいスレッドが作成されたが、次にスレッドで実行されるPrintHelloまでスケジュールされない場合。この状況では、スレッド関数での参照は、つまり、期待したものではありません。i++mainargumentmessage_num = *((int *) messageid);

これに対する解決策は、動的に(を使用してmalloc)割り当て、使用後にスレッド関数でそれらargumentを割り当てることです。free

于 2012-07-10T07:08:11.510 に答える
0

スカラー整数引数をスレッド関数に渡す1つの方法は、C99標準の§6.3.2.3からの次のテキストを(ab-)使用することです。

(5)整数は任意のポインタ型に変換できます。以前に指定された場合を除き、結果は実装定義であり、正しく整列されていない可能性があり、参照されたタイプのエンティティを指していない可能性があり、トラップ表現である可能性があります。

2番目の文の最後の部分を除いて、次のコードはほとんどのシステムで機能するはずです。

int int_val;
...
pthread_create(..., ..., thread_func, (void *)int_val);

そしてそれthread_funcを整数にキャストバックします:

void *thread_func (void *data)
{
    int int_arg = (int)data;
    ...
}
于 2012-07-10T08:43:33.120 に答える