2017-06-27 6 views
0

私はプロセス内に3つのスレッドth1、th2、th3を持ち、3つのレジスタ(配列)a、b、cを持っているとします。 th1とth2は3つのレジスタのうちの1つにのみ書き込みを行い、th3はこれらのレジスタからのデータの読み出しのみを行います。 th1、th2、th3は、条件変数を待つb/cの順番で動作します。 (th1、th2)と(th2、th3)との間のシグナリングのために、2つの条件変数cv1およびcv2がそれぞれ使用される。条件変数を使用したスレッド間通信?

  1. 最初のth1は、あるものを 'a'配列に書き込んだ後、それを待っていた信号(cv1を使用)th2を書き込みます。
  2. th1から信号を受信した後、th2は同じ配列 'a'に書き込みを開始し、次に 'a'を読み取るために(cv2を使用して)th3を通知します。
  3. th3はth2からの信号を受信すると 'a'(同じ配列)の読み取りを開始します。
  4. 上記の3つのステップは、同じ方法で 'b'と 'c'を繰り返します。

私のCのコードは以下の通りです:

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <pthread.h> 

void* th1(); 
void* th2(); 
void* th3(); 

int a[40], b[40], c[40], rn; 

pthread_mutex_t mutex1, mutex2, mutex3; 
pthread_cond_t cv1, cv2; 

int main() 
{ 
    pthread_t t[3]; 
    pthread_mutex_init(&mutex1, NULL); 
    pthread_mutex_init(&mutex2, NULL); 
    pthread_mutex_init(&mutex3, NULL); 

    pthread_cond_init(&cv1, NULL); 
    pthread_cond_init(&cv2, NULL); 

    pthread_create(&t[0], NULL, th1, NULL); 
    pthread_create(&t[1], NULL, th2, NULL); 
    pthread_create(&t[2], NULL, th3, NULL); 


    pthread_join(t[0], NULL); 
    pthread_join(t[1], NULL); 
    pthread_join(t[2], NULL); 

    pthread_mutex_destroy(&mutex1); 
    pthread_mutex_destroy(&mutex2); 
    pthread_mutex_destroy(&mutex3); 
    pthread_cond_destroy(&cv1); 
    pthread_cond_destroy(&cv2); 
    return 0; 
} 

void* th1() 
{  
    pthread_mutex_lock(&mutex1); 
     for(int i=0; i<20; i++) 
     { 
      a[i]=i; 
      } 
     pthread_cond_signal(&cv1); 
     puts("a signal sent..."); 
    pthread_mutex_unlock(&mutex1); 


    pthread_mutex_lock(&mutex2); 
     for(int i=0; i<20; i++) 
     { 
      b[i]=i; 
      } 
     pthread_cond_signal(&cv1); 
     puts("b signal sent..."); 
    pthread_mutex_unlock(&mutex2); 


    pthread_mutex_lock(&mutex3); 
     for(int i=0; i<20; i++) 
     { 
      c[i]=i; 
      } 
     pthread_cond_signal(&cv1); 
     puts("c signal sent..."); 
    pthread_mutex_unlock(&mutex3); 

    pthread_exit(NULL); 
} 

void* th2() 
{ 
    pthread_mutex_lock(&mutex1); 
     pthread_cond_wait(&cv1, &mutex1); 
     puts("signal recv form th1 for writing 'a'...\n"); 
     for(int i=0; i<=20; i++) 
     { 
      a[i+20]=i+20; 
     } 
     pthread_cond_signal(&cv2); 
    pthread_mutex_unlock(&mutex1); 


    pthread_mutex_lock(&mutex2); 
     pthread_cond_wait(&cv1, &mutex2); 
     puts("signal recv from th1 for writing 'b'...\n"); 
     for(int i=0; i<=20; i++) 
     { 
      b[i+20]=i+20; 
     } 
     pthread_cond_signal(&cv2); 
    pthread_mutex_unlock(&mutex2); 


    pthread_mutex_lock(&mutex3); 
     pthread_cond_wait(&cv1, &mutex3); 
     puts("signal recv from th1 for writing 'c'...\n"); 
     for(int i=0; i<=20; i++) 
     { 
      c[i+20]=i+20; 
     } 
     pthread_cond_signal(&cv2); 
    pthread_mutex_unlock(&mutex3); 

    pthread_exit(NULL); 
} 
void* th3() 
{ 

    pthread_mutex_lock(&mutex1); 
     pthread_cond_wait(&cv2, &mutex1); 
     puts(" signal recv from th2 for reading 'a'...\n"); 
     for(int i=0; i<=40; i++) 
     { 
      printf("%d :",a[i]); 
     } 
     printf("\n\n"); 
    pthread_mutex_unlock(&mutex1); 


    pthread_mutex_lock(&mutex2); 
     pthread_cond_wait(&cv2, &mutex2); 
     puts(" signal recv from th2 for reading 'b'...\n"); 
     for(int i=0; i<=40; i++) 
     { 
      printf("%d :",b[i]); 
     } 
     printf("\n\n"); 
    pthread_mutex_unlock(&mutex2); 


    pthread_mutex_lock(&mutex3); 
     pthread_cond_wait(&cv2, &mutex3); 
     puts(" signal recv from th2 for reading 'c'...\n"); 
     for(int i=0; i<=40; i++) 
     { 
      printf("%d :",c[i]); 
     } 
     printf("\n\n"); 
    pthread_mutex_unlock(&mutex3); 

    pthread_exit(NULL); 

} 

出力ブロックだけ表示した後:

[email protected]:~/Documents/rough$ gcc tread.c -o tread -lpthread 
[email protected]:~/Documents/rough$ ./tread 
a signal sent... 
b signal sent... 
c signal sent... 

私の予想出力のようなものである:、私は考えて

a signal sent 
    signal recv form th1 for writing 'a'... 
    signal recv from th2 for reading 'a'... 
    1 2 3 4 ..... 40 

    b signal sent 
    signal recv form th1 for writing 'b'... 
    signal recv from th2 for reading 'b'... 
    1 2 3 4 ..... 40 

    c signal sent 
    signal recv form th1 for writing 'c'... 
    signal recv from th2 for reading 'c'... 
    1 2 3 4 ..... 40 

私は条件変数がmとどのように連動するのか理解できませんでしたutexes。任意のヘルプ???

+0

'他のスレッドの前に送られてcond_signal'すなわち、他のスレッドでも、始まる前に最初のスレッドが実行されますそれを待つ時間があった場合、それらはさらに「待機」でブロックされます。 –

+0

解決策は何ですか? – mohtashim

答えて

0

イベント「信号」を統合する必要があります。信号(状態の変化を通知する)が発生した場合は、保存する必要があります。第1回イベント(「」読み)のようになりますあなたのコードの調整のために

int a_read = 0; /* to store the event "a had been read" actually happened */ 

void* th1(void * pvunused) 
{  
    pthread_mutex_lock(&mutex1); 
    for(int i=0; i<20; i++) 
    { 
     a[i]=i; 
    } 

    a_read = 1; 
    pthread_cond_signal(&cv1); 
    ... 


void* th2(void * pvunused) 
{ 
    pthread_mutex_lock(&mutex1); 
    while (0 == a_read) /* Theoretical an "if" would do here, 
         using "while" lets you stay on the safe side, in case 
         a "spurious wake-up" (https://en.wikipedia.org/wiki/Spurious_wakeup) 
         occurred. */ 
    { 
    pthread_cond_wait(&cv1, &mutex1); 
    } 

    ... 
+0

完璧!それはブロッキングウェイトコールが自動的に他のスレッドからのシグナルを受信するのではなく、呼び出されたスレッドからの 'work_end_flag'の一定のチェックを要求します。 – mohtashim

+0

@mohtashim: "*ブロッキング待機コールは自動的に他のスレッドからシグナルを受信しません* *もし*この "他の"スレッドが既に待っているのであれば、それは確かです。条件が合図されるのをまだ待っていない場合は、それが欠落します。それがなぜシグナルが送られたのかは、関連する条件変数によって行われる必要があります。 – alk

+0

私は誤解であると誤解している場合、正しい考え方を教えてください:th1が最初に実行され、mutex_lockとmutex_unlockの間のアトミックコードがセットされます。a_read == 1.th2が実行された後while(0 == a_read)が失敗します(b/c a_read == 1)th2の実際のpthread_cond_wait(&cv1、&mutex1)は、シグナルやその他のコードを外部で受け取ることはありませんが、ループは実行されません... – mohtashim

関連する問題