1

新人来了 我一直在研究读者/作家的问题解决方案。它适用于 1 位读者和 1 位作者。但是当我将 reader 修改为 2 时;作家线程总是饿死。帮我!

似乎 Writer 线程卡在某处等待 wrt 互斥锁。

#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();


}
4

2 回答 2

1

如果有 1 个以上的读取线程,很可能g_ReadCount永远不会为零,因此wrt互斥锁永远不会被释放(从而使写入器挨饿)。您可能需要某种指标来表明编写器线程正在等待。然后读者线程需要在某些时候优先考虑作者。

例如,在我编写的一个实现中(不是说这是一种好方法,但它确实有效)我使用了一个通过原子递增/递减操作设置/清除的标志,该标志指示写入器线程是否正在等待锁定。如果是这样,读者会推迟。当然,在这种情况下,您还需要注意相反的情况,即编写器线程(如果有多个)可能会使读者饿死。读/写锁很棘手。

于 2012-07-21T23:32:00.580 回答
0

在解决这个问题时;我发现了有趣的问题。

学习期间;我们告诉最大计数 = 1 的信号量等于互斥量。这并不完全正确。

1) Mutex 不能被任何其他线程释放。2)在这种情况下可以使用信号量。

于 2012-07-22T19:49:03.200 回答