Readers Writers - Writer thread always stuck with multiple reader thread

1000 views Asked by At

New bie here. I have been working on readers/ writers problem solution. It works perfectly fine with 1 reader and 1 writer. But when I modify reader to 2; writer thread always starves. Help me!

It seems Writer thread is stuck somewhere waiting for wrt mutex.

#include <stdio.h>
#include <conio.h>
#include <windows.h>

HANDLE mutex, wrt;
int g_ReadCount = 0;
int g_GlobalData=0;

const int max = 2;
HANDLE reader[max], writer[max];
CRITICAL_SECTION rSect, wSect;
bool bTerminate = true;

DWORD Readers(LPVOID lpdwThreadParam ) 
{
  while(bTerminate)
  {
    WaitForSingleObject(mutex, INFINITE);
    g_ReadCount++;
    if(g_ReadCount == 1)
    {      
      WaitForSingleObject(wrt, INFINITE);
    }
    ReleaseMutex(mutex);

    EnterCriticalSection(&wSect);
    printf("ThreadId : %d --> Read data : %d  ReaderCount %d\n", GetCurrentThreadId(), g_GlobalData, g_ReadCount);
    LeaveCriticalSection(&wSect);

    WaitForSingleObject(mutex, INFINITE);
    g_ReadCount--;
    if(g_ReadCount == 0)
    {
        ReleaseMutex(wrt);
        printf("ThreadId : %d Realesed Mutex wrt\n", GetCurrentThreadId());
    }
    printf("ThreadId : %d ReaderCount %d\n", GetCurrentThreadId(), g_ReadCount);
    ReleaseMutex(mutex);
    printf("Reader ThreadId : %d Realesed Mutex mutex\n", g_ReadCount);
    Sleep(0);
   }
  return 0;
}


DWORD Writers(LPVOID lpdwThreadParam ) 
{
  int n = GetCurrentThreadId();
  int temp = 1;
  while(bTerminate)
  {  
    printf("ThreadId : %d Waiting for WRT\n", GetCurrentThreadId());
    WaitForSingleObject(wrt, INFINITE);
    printf("WRITER ThreadId : %d ***Got  WRT\n", GetCurrentThreadId());
    ++n;
    temp++;

    if(temp == 100)
    {
      //bTerminate = false;
    }

    EnterCriticalSection(&wSect);
    printf("Write by ThreadId : %d Data : %d   Temp %d\n", GetCurrentThreadId(), n, temp);
    g_GlobalData = n;
    LeaveCriticalSection(&wSect);
    ReleaseMutex(wrt);
  }

  printf("***VVV***Exiting Writer Thread\n");
  return 0;
}

void main()
{
  mutex = CreateMutex(NULL, false, "Writer");
  wrt = CreateMutex(NULL, false, "wrt");

  InitializeCriticalSection(&rSect);
  InitializeCriticalSection(&wSect);
  DWORD dwThreadId = 0;



  for(int i=0; i < max; i++)
  {
    reader[i] = CreateThread(NULL, //Choose default security
      0, //Default stack size
      (LPTHREAD_START_ROUTINE)&Readers,
      //Routine to execute
      (LPVOID) 0, //Thread parameter
      0, //Immediately run the thread
      &dwThreadId //Thread Id
      );
  }

  for(int i=0; i < 1; i++)
  {
    writer[i] = CreateThread(NULL, //Choose default security
      0, //Default stack size
      (LPTHREAD_START_ROUTINE)&Writers,
      //Routine to execute
      (LPVOID) 0, //Thread parameter
      0, //Immediately run the thread
      &dwThreadId //Thread Id
      );
  }


  getchar();


}
2

There are 2 answers

1
Mark Wilkins On BEST ANSWER

With more than 1 reader thread, it is quite likely that g_ReadCount will never get to zero, so the wrt mutex will never be released (thus starving the writer). You probably need some kind of indicator that the writer thread is waiting. Then the reader threads would need to give precedence to the writer at some point.

For example, in one implementation I wrote (not saying it is a great way, but it worked) I used a flag that was set/cleared via atomic increment/decrement operations that indicated if a writer thread was waiting for the lock. If so, the readers would hold off. Of course, in that case you also need to then be careful of the opposite situation where writer threads (if more than one) could starve readers. Read/Write locks are tricky.

0
vipul On

While working on this problem; I found interesting issue.

During study; we told that Semaphore with max count =1 is equal to Mutex. That is not entirely true.

1) Mutex can not be released by any other thread. 2) Semaphore can be used in such situation.