Pavel Straka
Pavel Straka

Reputation: 427

Readers - writers in C - where am I wrong?

I would like to ask for help with this task.

My task is write an easy program in C which simulates readers-writers problem. The program requirements are:

  1. After program start, the user will be asked for enter count of writers and readers.

  2. Program will continously inform the user about status of the threads.

  3. After end of the program, little statistic (how many times had every reader read and every writer write).

I have done some basic structure of the program (dealing with the critical section through semaphores etc.), but I think that the program does not do, what it should do. Program runs without fault or unexpected behavior, but the counts, how many times had every reader read and every writer write are always one for each reader or writer).

Where am i wrong? Maybe I don't understand the task well.

Thank You very much for response.

Program code:

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

Output: Enter count of writers:4 Enter count of readers: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

Upvotes: 0

Views: 1243

Answers (2)

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53016

You can try this, but please pick vasicbre's answer because he is the one who found the problem first.

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

Upvotes: 1

vasicbre
vasicbre

Reputation: 86

Your output is perfectly correct since every thread you run does exactly one read/write. Put some loops in reader/writer functions to change that fact. Your program may encounter an error when you run it with 10 readers or writers because one of them will try to access writeCount[10] or readCount[10], change that and you have a correct program.

Upvotes: 2

Related Questions