Reputation: 55
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
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
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