0

私はcで2つのスレッドを持つ1つのプロデューサとコンシューマの問題を行っています。私はプロデューサーが何かを置いて消費者が同じリストからそれを取る共有リンクリストを使ってそれをしました。 2つの値NとB(Nは転送されるデータのサイズ、Bは共有リンクリストの最大サイズ)でコードを実行する必要があります。 (./thread-a1 N B) このコードは小さい値に対して正常に動作します。しかし、N = 20,000、B = 16の場合、Segmentationフォルトが発生します。11 なぜこのようなことが起こっているのかわかりません。助けてくださいより大きい値の場合producer-consumer c-segmentationフォールト

#include<time.h> 
#include<sys/time.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include<pthread.h> 
#include<unistd.h> 

struct job 
{ 
    int data; 
    struct job* next; 
}; 

struct job* head; 
int maxSize; 
int n; 
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 

int getCount() 
{ 
    int count = 0; 
    struct job* p = head; 
    while(p != NULL) 
    { 
     p = p -> next; 
     count++; 
    } 
    return count; 
} 

void Insert(int x) 
{ 

    struct job* temp = (struct job*)malloc(sizeof(struct job)); 
    temp -> data = x; 
    if (head == NULL) 
    { 
     temp -> next = NULL; 
    } 
    else 
    { 
     temp -> next = head; 
    } 
    head = temp; 
} 

void Delete() 
{ 

    struct job *toDelete, *secondLastNode; 

    if(head == NULL) 
    { 

    } 
    else 
    { 
     toDelete = head; 
     secondLastNode = head; 


     while(toDelete->next != NULL) 
     { 

      secondLastNode = toDelete; 
      toDelete = toDelete->next; 
     } 
     printf("%d, ", toDelete -> data); 

     if(toDelete == head) 
     { 
      free(toDelete); 
      head = NULL; 
     } 
     else 
     { 
      secondLastNode->next = NULL; 
      free(toDelete); 
     } 

    } 
} 

void* producer(void* arg) 
{ 
    pthread_mutex_lock(&m); 
    head = NULL; 

    int i; 
    for (i = 0; i<n; i++) 
    { 

     while(getCount() >= maxSize) 
     { 
      pthread_mutex_unlock(&m); 
     } 
     Insert(i); 
    } 

    return NULL; 
} 

void* consumer(void* arg) 
{ 
    pthread_mutex_lock(&m); 
    int i; 
    for (i=0; i<n; i++) 
    { 
     while(getCount() <= 0) 
     { 
      pthread_mutex_unlock(&m); 
     } 
     Delete(); 
    } 


    return NULL; 
} 

int main(int argc, char *argv[]) 
{ 

    struct timeval start_init, end_init; 
    gettimeofday(&start_init, NULL); 
    n = atoi(argv[1]); 
    maxSize = atoi(argv[2]); 

    pthread_t thread1; 
    pthread_t thread2; 
    gettimeofday(&end_init, NULL); 
    printf("Time elapsed for initialization is: %ld\n", 
     (long)(end_init.tv_sec*1000000 + end_init.tv_usec) - (start_init.tv_sec*1000000 + start_init.tv_usec)); 

    struct timeval start_trans, end_trans; 
    gettimeofday(&start_trans, NULL); 
    pthread_create(&thread1, NULL, &producer, NULL); 
    pthread_create(&thread2, NULL, &consumer, NULL); 

    pthread_join(thread1, NULL); 
    pthread_join(thread2, NULL); 
    gettimeofday(&end_trans, NULL); 
    printf("Time elapsed for transmission is: %ld\n", 
     (long)(end_trans.tv_sec*1000000 + end_trans.tv_usec) - (start_trans.tv_sec*1000000 + start_trans.tv_usec)); 


    return 0; 
} 
+0

プログラムでセグメンテーションが発生しますか? –

+0

'malloc'の戻り値を確認する必要があります。ゼロの場合、メモリ不足です。 –

+0

@PaulOgilvie:20Kの非常に小さな構造体は、どれも解放されなくてもメモリを使い果たしてしまうとは思わない。 –

答えて

3

ロックを再訪する必要があります。各プロデューサ&コンシューマの開始時にのみロックを取得し、それ以降はロックを解除する(繰り返し!)ので、これ以上の同期は行われません。プログラムの実行時間が長ければ長いほど、この同期の欠如がプログラムを上回る可能性が高くなります。

+1

これに加えて、「ビジー待機」とそれを回避する方法についても読んでください。 – johni

+1

@SukhmanWaraichすでにロックされているミューテックスのロックを解除しようとするとエラーが発生します。 'pthread_mutex_unlock'呼び出しをループに入れれば、問題が発生するだけです:https://linux.die.net/man/3/pthread_mutex_lock – yano

+1

@johniが言ったように。特に、条件変数はここでは良い選択肢、あるいは多分セマフォーのペアです。 –

0

私はあなたのロックがされるべきだと思う:getCountを含むすべての操作は、取得したロックを行わなければならないことを

void* producer(void* arg) 
{ 
    int i; 
    for (i = 0; i<n; i++) 
    { 
     pthread_mutex_lock(&m); 
     while(getCount() >= maxSize) 
     { 
      pthread_mutex_unlock(&m); // allow consumer to acquire lock 
      pthread_mutex_lock(&m);  // re-acquire lock 
     } 
     Insert(i); 
     pthread_mutex_lock(&m); 
    } 
    return NULL; 
} 

void* consumer(void* arg) 
{ 
    int i; 
    for (i=0; i<n; i++) 
    { 
     pthread_mutex_lock(&m); 
     while(getCount() <= 0) 
     { 
      pthread_mutex_unlock(&m); // allow producer to acquire lock 
      pthread_mutex_lock(&m);  // re-acquire lock 
     } 
     Delete(); 
     pthread_mutex_lock(&m); 
    } 
    return NULL; 
} 

注意。 (getCountをグローバル変数に置き換えることも考えてください;ロックされている間のみ操作してください)

+0

ありがとうポール。わかった – wander

関連する問題