2013-06-26 8 views
5

2つのスレッドが同じ関数を同時に呼び出し、その関数がソケット上にテキストを送信するUDPクライアントである場合はどうなるのだろうか。複数のpthreadが同じ関数を使用するとどうなるか

以下のコードを考慮して、私はそれを実行していますが、私はまだエラーがありません。私はスレッドが同じソース(関数、変数、IP、ポート)を同時に使用し、ソースをどのように共有するのであろうとクラッシュするはずですか?私は、以下のコードはマルチスレッドの使い方が間違っていると思いますが、他のスレッドが使用していない関数をスレッドが使用するようにスレッドをどのように使うべきか説明できますか?言い換えれば、どのようにスレッドセーフなのでしょうか? Linux上の例のCコードとして

:あなたはmsg_send内のソケットを作成し、閉じているので

void *thread1_fcn(); 
void *thread2_fcn(); 
void msg_send(char *message); 

int main(void){ 
    pthread_t thread1, thread2; 
    pthread_create(&thread1, NULL, thread1_fcn, NULL); 
    pthread_create(&thread2, NULL, thread2_fcn, NULL); 
    while(1){} 
    return 0; 
} 

void *thread1_fcn(){ 
    while(1){ 
     msg_send("hello"); 
     usleep(500); 
    } 
    pthread_exit(NULL); 
} 

void *thread2_fcn(){ 
    while(1){ 
     msg_send("world"); 
     usleep(500); 
    } 
    pthread_exit(NULL); 
} 

void msg_send(char message[]){ 
     struct sockaddr_in si_other; 
     int s=0; 
     char SRV_IP[16] = "192.168.000.002"; 

     s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
     memset((char *) &si_other, 0, sizeof(si_other)); 
     si_other.sin_family = AF_INET; 
     si_other.sin_port = htons(12346); 
     si_other.sin_addr.s_addr = htonl(INADDR_ANY); 
     inet_aton(SRV_IP, &si_other.sin_addr); 
     sendto(s, message, 1000, 0, &si_other, sizeof(si_other)); 
     close(s); 
} 
+2

同じ機能を呼び出す際に問題はありません(各スレッドは独自の実行コンテキストとスタックを持っています)。 *共有状態へのアクセスに問題があるかもしれません(ライブラリ呼び出しにおける共有状態を含む)。もしあれば共有状態がどのようなものかを見極めるためにコードの自己分析を検討し、この問題に焦点を当てます。 – user2246674

+1

自動変数の美しさは、自動的にすべてが機能することです。 –

+1

'thread1_fcn()'と 'thread12_fcn()'は、 'pthread_create()'が予期しているものと一致する 'void *'引数を取るように宣言されるべきです。 – jxh

答えて

3

、特別なことは何も起こりません。すべて正常に動作します。

3

コードに問題はありません。各スレッドは、たとえ同じコードを実行しても、別々のスタックを持っているので、別々の変数セットが動作します。変数は共有されません。

1

スレッドは、小さな文字列リテラルをmessage引数として渡しますが、関数はmessageベースアドレスから1000バイトを送信しようとするため、未定義の動作を呼び出します。

sendtoはオペレーティングシステムへの直接の呼び出しであることが多いので、UDPで多量のゴミを送信するか、システムコールが境界外のメモリアクセスを検出してリターンするか-1とerrnoはEFAULTのように設定されています(データを送信していない可能性が高いです)。

messageは文字列なので、長さを計算してから、ヌルターミネータの有無にかかわらず、それだけを送信する必要があります。受信者は、データグラムの長さからヌル終了文字列を再構成できます。 )

しかし、この関数は並行性の問題を引き起こしません。

sendto複数のスレッドが同じソケットでそれを呼び出す場合でも、関数は安全です。しかし、ストリームソケットでこれを行うと、予測できない方法でデータがバイトストリームにインターリーブされるという問題が発生する可能性があります。

関連する問題