I have an easy program for simulating readers-writers problem in C. User is asked to enter count of writers and count of readers. And then random number of writer - threads and reader - threads is created. The writing of items is simulated by global variable itemsCount - it represent thee ID of new inserted item (itemsCount + 1). I think that to this point the program works well.
But now i have to show writing conflict that is caused by bad written synchronization. I thought that is enough to simply remove the statement sem_wait(&w);
or badly initilaizate the semaphore - for example sem_init(&w,0,5);
But it does nothing, i can't see any writing conflict. I thought, that in the output i will see something like:
Writer 1 writes item --> number of item: 1 | name of item: Writer 1
Writer 2 writes item --> number of item: 1 | name of item: Writer 2
(conflict: two items with one number). But none of this happens.
Where am i wrong?
Code with good synchronization:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define MAX_READERS 10
#define MAX_WRITERS 10
sem_t w; // semaphor for write access
sem_t m; // mutex
int rc=0; // readers count
int writersCount; // how many writers does user want
int readersCount; // how many readers does user want
pthread_t writersThread[MAX_WRITERS*5], readersThread[MAX_READERS*5]; // threads for writers and readers
int writeCount[MAX_WRITERS], readCount[MAX_READERS]; // how many times did each writer write and each reader read
int itemsCount=0; // how many items is stored in the "DB"
void *writer(void *i)
{
int a = *((int *) i);
sem_wait(&w); // P(w)
printf("Writer %d writes item --> number of item: %d | name of item: Writer %d\n", a+1, ++itemsCount, a+1);
writeCount[a]++;
sem_post(&w); // V(w)
return 0;
}
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]++;
sem_wait(&m); // P(m)
rc--;
if (rc == 0) {
sem_post(&w); // V(w)
}
sem_post(&m); // V(m)
return 0;
}
int randomCount() // returns random integer between 1 and 5
{
return 1 + 5.0 * rand() / RAND_MAX;
}
int main()
{
srand(time(NULL));
sem_init(&w,0,1); // semaphore initialization
sem_init(&m,0,1);
int i;
printf("Enter count of writers (max. %d):", MAX_WRITERS);
scanf("%d",&writersCount);
if (writersCount > MAX_WRITERS) {
fprintf(stderr, "Max count of wirters is: %d\n", MAX_WRITERS);
return 1;
}
printf("Enter count of readers (max. %d):", MAX_READERS);
scanf("%d",&readersCount);
if (writersCount > MAX_READERS) {
fprintf(stderr, "Max count of readers is %d\n", MAX_READERS);
return 1;
}
printf("---------------------------------------------\n");
int readerIndexes[readersCount]; // reader indexes (will be passed to thread)
int writerIndexes[readersCount]; // writer indexes (will be passed to thread)
int totalReaders = 0;
int totalWriters = 0;
for (i=0; i<readersCount; i++) // create readers (how many did user enter)
{
int j;
int count;
readerIndexes[i] = i;
count = randomCount();
for (j=0; j<count; j++) // let the reader read randomly from 1 to 5 times
{
pthread_create(&readersThread[totalReaders++], NULL, reader, &readerIndexes[i]);
}
}
for (i = 0 ; i < writersCount ; i++) // create writers (how many did user enter)
{
int j;
int count;
writerIndexes[i] = i;
count = randomCount();
for (j=0;j<count;j++) // let the writer write randomly from 1 to 5 times
{
pthread_create(&writersThread[totalWriters++], NULL, writer, &writerIndexes[i]);
}
}
for (i=0;i<totalWriters;i++) // join the threads
{
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]);
}
for (i=0;i<writersCount;i++)
{
printf("Writer %d wrote %d times\n", i+1, writeCount[i]);
}
sem_destroy(&w);
sem_destroy(&m);
return 0;
}
Output:
Enter count of writers (max. 10):5
Enter count of readers (max. 10):5
---------------------------------------------
Reader 1 reads from DB.
Reader 1 reads from DB.
Reader 2 reads from DB.
Reader 2 reads from DB.
Reader 2 reads from DB.
Reader 2 reads from DB.
Reader 3 reads from DB.
Reader 3 reads from DB.
Reader 4 reads from DB.
Reader 4 reads from DB.
Reader 4 reads from DB.
Writer 1 writes item --> number of item: 1 | name of item: Writer 1
Writer 1 writes item --> number of item: 2 | name of item: Writer 1
Writer 1 writes item --> number of item: 3 | name of item: Writer 1
Writer 2 writes item --> number of item: 4 | name of item: Writer 2
Writer 2 writes item --> number of item: 5 | name of item: Writer 2
Writer 2 writes item --> number of item: 6 | name of item: Writer 2
Writer 3 writes item --> number of item: 7 | name of item: Writer 3
Writer 3 writes item --> number of item: 8 | name of item: Writer 3
Writer 3 writes item --> number of item: 9 | name of item: Writer 3
Writer 3 writes item --> number of item: 10 | name of item: Writer 3
Writer 4 writes item --> number of item: 11 | name of item: Writer 4
Writer 5 writes item --> number of item: 12 | name of item: Writer 5
Writer 5 writes item --> number of item: 13 | name of item: Writer 5
Writer 5 writes item --> number of item: 14 | name of item: Writer 5
Reader 4 reads from DB.
Reader 4 reads from DB.
Reader 5 reads from DB.
Reader 5 reads from DB.
Reader 5 reads from DB.
Reader 5 reads from DB.
---------------------------------------------
Reader 1 read 2 times
Reader 2 read 4 times
Reader 3 read 2 times
Reader 4 read 5 times
Reader 5 read 4 times
Writer 1 wrote 3 times
Writer 2 wrote 3 times
Writer 3 wrote 4 times
Writer 4 wrote 1 times
Writer 5 wrote 3 times
Thank You very much