编写以下代码是为了从文件中获取整数到缓冲区并从缓冲区中读取它们。有两个写入器线程将整数从文件读取到缓冲区,两个读取器线程从缓冲区读取整数。缓冲区大小为 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/