2

循環バッファーを実装し、別のスレッドで文字を追加および削除する必要がある宿題があります。

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

#define QSIZE 10

pthread_cond_t full,/* count == QSIZE */ 
           empty,/* count == 0 */ 
           ready;
pthread_mutex_t m, n; /* implements critical section */ 
unsigned int iBuf, /* tail of circular queue */ 
         oBuf; /* head of circular queue */ 
int count; /* count characters */ 
char buf [QSIZE]; /* the circular queue */ 

void Put(char s[]) {/* add "ch"; wait if full */
    pthread_mutex_lock(&m); 
    int size = sizeof(s)/sizeof(char);
    printf("size: %d", size);

    int i;
    for(i = 0; i < size; i++) {
        while (count >= QSIZE) 
            pthread_cond_wait(&full, &m);/* is there empty slot? */ 

        buf[iBuf] = s[i]; /* store the character */ 
        iBuf = (iBuf+1) % QSIZE; /* increment mod QSIZE */ 
        count++; 
        if (count == 1) 
            pthread_cond_signal(&empty);/* new character available */ 
    }
    pthread_mutex_unlock(&m); 
} 
char Get() {/* remove "ch" from queue; wait if empty */ 
    char ch; 

    pthread_mutex_lock(&m); 
    while (count <= 0) 
        pthread_cond_wait(&empty, &m);/* is a character present? */ 

    ch = buf[oBuf]; /* retrieve from the head of the queue */ 
    oBuf = (oBuf+1) % QSIZE; 
    count--; 
    if (count == QSIZE-1) 
        pthread_cond_signal(&full);/* signal existence of a slot */ 

    pthread_mutex_unlock(&m); 
    return ch; 
} 

void * p1(void *arg) {
    int i;
    for (i = 0; i < 5; i++) {
        Put("hella");
    }
}

void * p2(void *arg) {
    int i;
    for (i = 0; i < 5; i++) {
        Put("goodby");
    }
}

int main() { 
    pthread_t t1, t2;
    void *r1, *r2;
    oBuf = 0; iBuf = 0; count=0; /* all slots are empty */ 

    pthread_cond_init(&full, NULL); 
    pthread_cond_init(&empty, NULL); 
    pthread_mutex_init(&m, NULL); 

    pthread_create(&t1, NULL, p1, &r1);
    pthread_create(&t2, NULL, p2, &r2);

    printf("Main");
    char c;
    int i = 0;
    while (i < 55) {
        c = Get();
        printf("%c",c);
        i++;
    }

    pthread_join(t1, &r1);
    pthread_join(t2, &r2);
    return 0; 
}

ロジックをまったく変更する必要はありません。要件はかなり具体的です。私の問題は Put() メソッドにあると思います。最初のスレッドが入ってクリティカル セクションをブロックし、デッドロックを引き起こしていると思います。スケジューリング属性を作成する必要があると考えていましたか? もちろん、私は間違っているかもしれません。私は pthreads と並行プログラミングにかなり慣れていないので、エラーを見つけるのに本当に役立つことができました。

4

1 に答える 1

1

これを解決する 1 つの方法は、循環キューの先頭と末尾を管理する別のミューテックスを用意することです。このように、バッファがいっぱいであるためにライターがブロックされても、リーダーはブロックされません。

別の解決策は、バッファーがいっぱいまたは空の状態になった場合にミューテックスを解放し、状態がクリアされたときに再取得することです。

-ルー

于 2011-06-27T19:11:22.177 に答える