C - 带 pthreads 的循环字符缓冲区

发布于 2024-11-17 07:01:24 字数 2412 浏览 5 评论 0原文

我有一个家庭作业,我必须实现一个循环缓冲区,并使用单独的线程添加和删除字符:

#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 和并发编程非常陌生,所以我真的需要一些帮助来发现我的错误。

I have a homework assignment where I have to implement a circular buffer and add and remove chars with separate threads:

#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; 
}

I shouldn't have to change the logic much at all, the requirements are pretty specific. I think my problem lies in the Put() method. I think the first thread is going in and blocking the critical section and causing a deadlock. I was thinking I should make a scheduling attribute? Of course I could be wrong. I am pretty new to pthreads and concurrent programming, so I could really use some help spotting my error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自由范儿 2024-11-24 07:01:25

解决这个问题的一种方法是使用单独的互斥体来管理循环队列的头部和尾部。这样,由于缓冲区已满而阻塞的写入器不会阻塞读取器。

另一种解决方案是,如果遇到缓冲区满或空的情况,则释放互斥体,并在条件清除时重新获取。

-楼

One way to solve this would be to have separate mutexes to manage the head and tail of the circular queue. This way, a writer blocking because the buffer is full will not block a reader.

Another solution would be to release the mutex if you run into the buffer full or empty conditions and reacquire when the condition clears.

-lou

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文