新的bie在这里。 我一直在努力解决读者/作者的问题。 它与1个阅读器和1个作家完美的工作。 但是当我把读者修改为2时, 作家线程总是饿死。 帮我!
看来作家线程卡在某处等待互斥量。
#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(); }
使用多于一个的g_ReadCount
线程,很有可能g_ReadCount
永远不会变为零,所以wrt
互斥将永远不会被释放(从而使作者挨饿)。 您可能需要某种指示器,即写入器线程正在等待。 那么读者线程就需要在某个时候优先考虑作者。
例如,在我写的一个实现中(不是说这是一个很好的方法,但是它的工作原理)我使用了一个通过原子递增/递减操作设置/清除的标志,指示写入程序线程是否正在等待锁定。 如果是这样,读者会坚持下去。 当然,在这种情况下,你还需要注意写作者线索(如果不止一个)可能会使读者挨饿的相反情况。 读/写锁是棘手的。
在解决这个问题的同时, 我发现有趣的问题。
在学习期间; 我们告诉max count = 1的信号量等于互斥量。 这不完全正确。
1)互斥锁不能被任何其他线程释放。 2)在这种情况下可以使用信号量。