technik
technik

Reputation: 55

Readers-Writers problem with pthreads resulting in only 1 reader

A task I have is to create a solution to the readers-writers problem with posix pthreads. I spawn 3 readers and 1 writer.

The task spec asks to add values to the queue 2 at a time (writers). The readers dequeue one at a time (when there exists a value in the queue). The queue has been tested and works.

The problem I have is when running the program, it results in only 1 reader thread actually reading most of the time. Sometimes repeated execution will result in all 3 readers being used. But most of the time its just 1 reader being used. I am not sure why this strange behavior occurs.

Thanks in advance.

Expected (Sometimes): 
TID: -684419328
TID: -684419328
TID: -673929472
TID: -673929472
TID: -694909184
TID: -694909184
...
Actual (Sometimes): 
TID: -684419328
TID: -684419328
TID: -684419328
TID: -684419328
TID: -684419328
TID: -684419328
...
pthread_cond_t qServiced = PTHREAD_COND_INITIALIZER;
pthread_cond_t qElement = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#include "rw.h"
#include "queue.h"

queue* q; 

void* reader()
{
    int serviced = 0; 
    int x; 

    while(!fin)
    {
        pthread_mutex_lock(&mutex);
        counter++; 

        while(isEmpty(q))
        {
            pthread_cond_signal(&qEmpty);
            pthread_cond_wait(&qElement, &mutex); e 
        }

        printf("TID: %d\n", (int)pthread_self());

        num* n = dequeue(q); //Take one task 

        printf("Num1: %d\n", n->num1);
        printf("Num2: %d\n", n->num2);

        serviced++;
        pthread_cond_signal(&qServiced); //Signal that task has been serviced
        pthread_mutex_unlock(&mutex);
    }
}

Upvotes: 1

Views: 186

Answers (2)

MayurK
MayurK

Reputation: 1957

Threads get scheduled by the scheduler in a one of the scheduling mechanism. But as a programmer, you should assume that it can be any random way and code.

By saying "random way", I mean all threads can get scheduled once in the course of the program or only one thread gets scheduled in the entire course.

Thread may get scheduled in a random way. I hope this answers your question.

If you want a specific way by which the execution should happen (example: All threads read once before a thread read for the second time) then you have to code accordingly. You can use mutex, semaphores, condition signals, flags and a combination of all these to achieve this.

Upvotes: 1

user3629249
user3629249

Reputation: 16540

The following proposed code is only for the 'read()' thread, but should give you an idea as to how to write the threads.

void* reader( void *arg )
{
    int *fin = (int*)arg;

    int serviced = 0; 

    while( !(*fin) )
    {
        printf("TID: %d\n", (int)pthread_self());

        pthread_mutex_lock(&mutex);
        counter++; 
        num* n = dequeue(q); //Take one task 
        pthread_mutex_unlock(&mutex);

        if( n )
        {
            printf("Num1: %d\n", n->num1);
            printf("Num2: %d\n", n->num2);
            serviced++;
        }

        else
        {
            printf( "no queue entries available\n" );
            sleep(1);
        }
    }
    pthread_exit( NULL );
}

note that the mutex is only locked when the thread is performing actions that could result in a 'race' condition.

The proposed code assumes (since the queue handling code was never posted) that dequeue() returns NULL if the queue is empty

Note: when no queue entry available, the thread sleeps for a while

This assumes that the main() function, passes the address of 'fin' as a parameter in the call to pthread_create()

Upvotes: 2

Related Questions