Reputation:
I have a few problems I can't solve in implementing WRITER-READER problem in UNIX. First one is that I have no idea, how can I modify the code to work like threads are always calling to enter reading room. For example, when a writer is in the reading room, readers are waiting to access the reading room. When writer is escaping the reading room and readers are entering the reading room, he still is waiting for his chance. The second one is that I have no idea how to modify the code to allow a few readers to enter the reading room. In my code only one thread can be in the same time in the reading room. The third one is, how to recognize if writer or reader is starving? Which one is starving in my code?
Here is the code:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define READERS 15
#define WRITERS 10
int bufferw = 0, bufferr = 0, counterw = WRITERS, counterr = READERS;
int i;
pthread_mutex_t mwrite, mread;
pthread_cond_t condw, condr;
pthread_t r[READERS], w[WRITERS];
void *writer(void *ptr) {
pthread_mutex_lock(&mwrite);
{
counterr = READERS;
counterw = WRITERS;
++bufferw;
for(i=0; i<READERS; i++) while(bufferr > 0) pthread_cond_wait(&condw, &r[i]);
printf("WRITER ENTERING!");
pthread_mutex_unlock(&mwrite);
bufferw--;
}
pthread_cond_signal(&condr);
pthread_exit(0);
}
void *reader(void *ptr) {
counterr = READERS;
counterw = WRITERS;
{
++bufferr;
for(i=0; i<WRITERS; i++) while(bufferw == 1) pthread_cond_wait(&condr, &w[i]);
printf("READER ENTERING!");
bufferr = 0;
}
pthread_cond_signal(&condw);
pthread_exit(0);
}
int main(int argc, char* argv[]) {
pthread_mutex_init(&mwrite, 0);
pthread_mutex_init(&mread, 0);
pthread_cond_init(&condw, 0);
pthread_cond_init(&condr, 0);
for(i=0; i<WRITERS; i++) pthread_create(&w[i], NULL, writer, NULL);
for(i=0; i<READERS; i++) pthread_create(&r[i], NULL, reader, NULL);
for(i=0; i<WRITERS; i++) pthread_join(w[i], NULL);
for(i=0; i<READERS; i++) pthread_join(r[i], NULL);
pthread_cond_destroy(&condw);
pthread_cond_destroy(&condr);
pthread_mutex_destroy(&mwrite);
pthread_mutex_destroy(&mread);
return 0;
}
Thanks in advance for your help!
EDIT:// How can I avoid race in this case?
Upvotes: 1
Views: 2756
Reputation: 3022
you could use one mutex and two conditional variables to implement this.
reader( ) {
pthread_mutex_lock(&m);
while (!(writers == 0))
pthread_cond_wait(&readersQ, &m);
readers++;
pthread_mutex_unlock(&m);
/* actual read */
pthread_mutex_lock(&m);
if (--readers == 0)
pthread_cond_signal(&writersQ);
pthread_mutex_unlock(&m);
}
writer( ) {
pthread_mutex_lock(&m);
writers++;
while (!((readers == 0) && (active_writers == 0))) {
pthread_cond_wait(&writersQ, &m);
}
active_writers++;
pthread_mutex_unlock(&m);
/* actual write */
pthread_mutex_lock(&m);
writers--;
active_writers--;
if (writers > 0)
pthread_cond_signal(&writersQ);
else
pthread_cond_broadcast(&readersQ);
pthread_mutex_unlock(&m);
}
This implementation is unfair to the readers, which means if there is a writer writing, readers will never get a choice to read. This is because writing is more important than reading. If you don't think so, I can also provide a version which is unfair to writers.
The reader will get a choice to read only when writers are equal to zero. If there is a single writer, the writer will not be zero and the reader cannot read.
If there are multiple writers, the variable active_writers will make sure that only one writer could write at a time.
EDIT
below is the version starve writers. For the reader, it is the same code.
writer( ) {
pthread_mutex_lock(&m);
while(!((readers == 0) &&(writers == 0)))
pthread_cond_wait(&writersQ, &m);
writers++;
pthread_mutex_unlock(&m);
/* actual write */
pthread_mutex_lock(&m);
writers--;
pthread_cond_signal(&writersQ);
pthread_cond_broadcast(&readersQ);
pthread_mutex_unlock(&m);
}
Upvotes: 3