读者 - C中的作家 - 我错在哪里?

时间:2015-01-13 21:44:45

标签: c multithreading io

我想请求帮助完成这项任务。

我的任务是在C中编写一个简单的程序,模拟读者编写者的问题。计划要求是:

  1. 程序启动后,将要求用户输入作者和读者的数量。

  2. 程序将不断通知用户线程的状态。

  3. 程序结束后,几乎没有统计数据(每个读者阅读的次数和每个作者都写了多少次)。

  4. 我已经完成了程序的一些基本结构(通过信号量处理关键部分等),但我认为该程序没有做,它应该做什么。程序运行没有错误或意外行为,但计数,每个读者读取的次数以及每个作者写入对于每个读者或作者来说总是一次。)

    我哪里错了?也许我不太了解这项任务。

    非常感谢您的回复。

    程序代码:

    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    sem_t w;    // write access
    sem_t m;    // mutex
    int rc=0;   // readers count
    
    int writersCount;
    int readersCount;
    pthread_t writersThread[10], readersThread[10];
    int writeCount[10], readCount[10];
    int i;
    
    void *writer(void *i) {
        int a = *((int *) i);
    
        sem_wait(&w);   // P(w)
        printf("Writer %d writes to DB.\n",a+1);
        writeCount[a+1]++;  
        sem_post(&w);   // V(w)
    
        free(i);
    }
    
    void *reader(void *i) {
        int a = *((int *) i);
    
        sem_wait(&m);   // P(m)
        rc++;
        if (rc == 1) {
            sem_wait(&w);   // P(w)
        }
        sem_post(&m);   // V (m)
    
        printf("Reader %d reads from DB.\n",a+1);
        readCount[a+1]++;   
    
        sem_wait(&m);   // P(m)
        rc--;
        if (rc == 0) {
            sem_post(&w);   // V(w)
        }
        sem_post(&m);   // V(m)
    
        free(i);
    }
    
    int main() {
        sem_init(&w,0,1);
        sem_init(&m,0,1);
    
        printf("Enter count of writers:");
        scanf("%d",&writersCount);
        printf("Enter count of readers:");
        scanf("%d",&readersCount);
    
        for (i=0; i<readersCount; i++) {
            int *arg = malloc(sizeof(*arg));
            *arg = i;
            pthread_create(&readersThread[i], NULL, reader, arg);
        }
        for (i=0; i<writersCount; i++) {
            int *arg = malloc(sizeof(*arg));
            *arg = i;
            pthread_create(&writersThread[i], NULL, writer, arg);
        }
        for (i=0; i<writersCount; i++) {
            pthread_join(writersThread[i], NULL);
        }   
        for (i=0; i<readersCount; i++) {
            pthread_join(readersThread[i], NULL);
        }
    
        printf("--------------\n");
        for (i=0; i<readersCount; i++) {
            printf("Reader %d read %d times\n",i+1,readCount[i+1]);
        }
    
        for (i=0; i<writersCount; i++) {
            printf("Writer %d wrote %d times\n",i+1,writeCount[i+1]);
        }
    
        sem_destroy(&w);
        sem_destroy(&m);
        return 0;
    }
    

    输出:     输入作者数:4     输入读者人数:4

    Reader 1 reads from DB.
    Reader 3 reads from DB.
    Reader 4 reads from DB.
    Reader 2 reads from DB.
    Writer 1 writes to DB.
    Writer 2 writes to DB.
    Writer 3 writes to DB.
    Writer 4 writes to DB.
    --------------
    Reader 1 read 1 times
    Reader 2 read 1 times
    Reader 3 read 1 times
    Reader 4 read 1 times
    Writer 1 wrote 1 times
    Writer 2 wrote 1 times
    Writer 3 wrote 1 times
    Writer 4 wrote 1 times
    

2 个答案:

答案 0 :(得分:2)

您的输出完全正确,因为您运行的每个线程都只执行一次读/写操作。在读取器/写入器函数中放置一些循环来改变这一事实。当您使用10位读者或作者运行该程序时,您的程序可能会遇到错误,因为其中一位读者将尝试访问writeCount[10]readCount[10],更改该程序并获得正确的程序。

答案 1 :(得分:0)

你可以试试这个,但请选择 vasicbre 的答案,因为他是第一个发现问题的人。

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

sem_t w;    // write access
sem_t m;    // mutex
int rc=0;   // readers count

int writersCount;
int readersCount;
pthread_t writersThread[100], readersThread[100];
int writeCount[10], readCount[10];

void *writer(void *i)
{
    int a = *((int *) i);

    sem_wait(&w);   // P(w)
    printf("Writer %d writes to DB.\n",a+1);
    writeCount[a + 1]++;
    sem_post(&w);   // V(w)

    return NULL;
}

void *reader(void *i)
{
    int a = *((int *) i);

    sem_wait(&m);   // P(m)
    rc++;
    if (rc == 1) {
        sem_wait(&w);   // P(w)
    }
    sem_post(&m);   // V (m)

    printf("Reader %d reads from DB.\n", a + 1);
    readCount[a + 1]++;

    sem_wait(&m);   // P(m)
    rc--;
    if (rc == 0) {
        sem_post(&w);   // V(w)
    }
    sem_post(&m);   // V(m)

    return NULL;
}

int randomCount()
{
    return 5.0 * rand() / RAND_MAX;
}

int main()
{
    sem_init(&w,0,1);
    sem_init(&m,0,1);

    int i;

    printf("Enter count of writers:");
    scanf("%d",&writersCount);
    printf("Enter count of readers:");
    scanf("%d",&readersCount);

    int readerIndices[readersCount];
    int writerIndices[writersCount];
    int totalReaders = 0;
    int totalWriters = 0;

    for (i=0; i<readersCount; i++)
    {
        int j;
        int count;

        readerIndices[i] = i;
        count            = randomCount();
        for (j = 0 ; j < count ; ++j)
        {
            pthread_create(&readersThread[totalReaders++], NULL, reader, &readerIndices[i]);
        }
    }

    for (i = 0 ; i < writersCount ; i++)
    {
        int j;
        int count;

        writerIndices[i] = i;
        count            = randomCount();
        for (j = 0 ; j < count ; ++j)
        {
            pthread_create(&writersThread[totalWriters++], NULL, writer, &writerIndices[i]);
        }
    }

    for (i = 0 ; i < totalWriters ; i++)
    {
        pthread_join(writersThread[i], NULL);
    }

    for (i = 0 ; i < totalReaders ; i++)
    {
        pthread_join(readersThread[i], NULL);
    }

    printf("--------------\n");
    for (i = 0 ; i < readersCount ; i++)
    {
        printf("Reader %d read %d times\n", i + 1, readCount[i + 1]);
    }

    for (i = 0 ; i < writersCount ; i++)
    {
        printf("Writer %d wrote %d times\n", i + 1, readCount[i + 1]);
    }

    sem_destroy(&w);
    sem_destroy(&m);
    return 0;
}