c - 如何使用多个写入器和多个读取器来实现 Readers Writers

标签 c linux multithreading pthreads mutex

编写以下代码是为了从文件中获取整数到缓冲区并从缓冲区中读取它们。有两个写入器线程将整数从文件读取到缓冲区,两个读取器线程从缓冲区读取整数。缓冲区大小为 5,文件中可以有任意数量的整数。写入线程必须将文件中的所有整数写入缓冲区,读取线程必须通过缓冲区读取文件中的所有整数。读者无法直接访问该文件。由于缓冲区大小为 5,当编写器将数据写入缓冲区并且缓冲区已满时,我放置了一个 pthread_cond_signal(&r) 来通知读取器它应该开始读取。但是读者继续打印零而不终止。我注释掉了读者部分和作者部分工作但它没有打印文件的第一个整数并且两个作者线程都读取了最终整数。 (写入器线程 1 读取 100,写入器线程 2 读取 100。因此缓冲区包含两个 100)有人可以指出错误吗?

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define BUF_SIZE 5


pthread_mutex_t m;
pthread_cond_t  r;
pthread_cond_t w;
FILE *fp;

int cnt_r= 0;
int flag =0;
int value;
int buf[BUF_SIZE];
int cnt = 0;
int z = 0;



void *read(void *parm);
void *write(void *parm);

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

    pthread_t rid[2];
    pthread_t wid[2];

    pthread_cond_init(&r,NULL);
    pthread_cond_init(&w,NULL);


    if ((fp = fopen("/home/bhagi/2/shared_data.txt", "r")) == NULL)
        fprintf(stderr, "Couldn't find the file");


    for( int i = 0; i< 2; i++)
    {
        printf("Writer %d Starts \n",i+1);
        pthread_create(&wid[i], NULL, write,i);
    }


    for(int i = 0; i < 2; i++)
    {
        printf("Reader %d Starts \n",i+1);
        pthread_create(&rid[i],NULL,read,i);
    }

    for(int i = 0; i < 2; i++)
    {
        pthread_join(rid[i],NULL);
    }


    for(int i = 0; i < 2; i++)
    {
        pthread_join(wid[i], NULL);
    }

    fclose(fp);


    return 0;
}

void *read(void *parm)
{

    int y = (int)parm;
    int cnt_r = 0;

    pthread_mutex_lock(&m);

        while (cnt == -1)
        {
            printf("Reader %d waits \n",y+1);
            pthread_cond_wait(&r, &m);
        }
        cnt++;

    printf("Reader %d Access CS\n",y+1);
     while(flag != -1)
     {
         for(int i = 0; i < 5;i++)
         {
             printf("%d ",buf[i]);
             cnt_r++;
             sleep(1);

         }
     printf("\n %d \n",cnt_r);
     }


     cnt--;
     if(cnt == 0)
        pthread_cond_signal(&w);

    if(cnt_r != 0)
    {
        pthread_cond_signal(&r);
        printf("Reader %d Signal Reader\n",y +1);
    }
     pthread_mutex_unlock(&m);



}

void *write(void *parm)
{

    int x = (int)parm;
    int cnt_w = 0;

    while(fscanf(fp,"%d",&value) == 1)
    {

        pthread_mutex_lock(&m);
        while(cnt!= 0) {
            printf("Writer %d waits \n", x + 1);
            pthread_cond_wait(&w, &m);
        }
        cnt++;

        printf("Writer %d access cs \n",x+1);
        cnt = 0;
        pthread_cond_signal(&w);


        if(z == 5)
        {
            z = 0;
            pthread_cond_signal(&r);


        }

        buf[z] = value;
        printf("buf = %d\n",buf[z]);
        ++z;
        cnt_w++;


        sleep(1);
        printf("%d\n",cnt_w);



        pthread_mutex_unlock(&m);


    }

    flag = -1;

}

最佳答案

由于缓冲区大小为 5,当编写器将数据写入缓冲区且缓冲区已满时,我放置了一个 pthread_cond_signal(&r)

这是倒退的事情。一般的多读写模式是:

  • 编写者等到缓冲区满,然后尽可能多地写入,然后向读者发出信号;
  • reader(s) 等到缓冲区为空,然后尽可能多地读取,然后向 writer 发出信号。

您需要对此进行扩充,以便您的读者知道何时退出:

  • 编写者等到缓冲区满,然后尽可能多地写入,然后向读者发出信号。如果写入器到达 EOF,它会设置文件结束标志并向所有 读者发出信号;
  • 读者等到缓冲区为空或设置了文件结束标志。在缓冲区不为空的情况下,他们会尽可能多地读取,然后向写入器发出信号;在设置文件结束标志的情况下,它们退出。

就您当前代码中的具体问题而言,我认为最突出的两个问题是:

  • flag 被编写者在没有持有互斥量的情况下访问(这可能是读者无限循环的原因,因为编译器可以假设 flag 永远不会在读取器持有互斥锁时更改);
  • value 应该是编写器中的局部变量,但它是共享的(并且访问未同步)——这可能是您的编写器从文件中看到相同数字的原因。

关于c - 如何使用多个写入器和多个读取器来实现 Readers Writers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50629797/

相关文章:

c - C 中的程序在 OS X 上有问题,但在 Windows 上没有

c - Main 端出现段错误,提供 GDB 输出

c - 将共享库注入(inject)流程

c# - 如果我从 Albahari 的生产者/消费者队列实现中删除 lock() 会发生什么

C++多线程 - 与线程合并排序的算法替代

java - 如何确保在主线程停止之前停止所有线程?

编译 OpenGL 和 GLUT OSX

c - Openocd:将值写入闪存地址

linux - linux/include/asm 中的 asm 代表什么

linux - 在 linux 中创建大型稀疏图像的校验和