参考地址:http://blog.csdn.net/morewindows/article/details/7596034
读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者在读文件时写者也不去能写文件。类似于生产者消费者问题的分析过程,首先来找找哪些是属于“等待”情况。
第一.写者要等到没有读者时才能去写文件。
第二.所有读者要等待写者完成写文件后才能去读文件。
参考博客里边有Bug,自己想着写的,不知道还有问题没,欢迎拍砖。。。。。。
解法一:
1 #include <iostream> 2 #include <string> 3 #include <Windows.h> 4 #include <process.h> 5 using namespace std; 6 7 /************************************************************************************ 8 9 模拟读者写者问题:1个写者,5个读者 10 11 *************************************************************************************/ 12 13 CRITICAL_SECTION g_csStdout; 14 CRITICAL_SECTION g_csReaderCnt; 15 CRITICAL_SECTION g_csReaderWriter;//防止在没有读者也没有写者的情况下出现同时读写的情况 16 const int READER_NUM = 5; //读者个数 17 HANDLE g_EventNoReader; 18 HANDLE g_EventNoWriter; 19 int g_nCurrentReaderCnt; 20 21 //设置控制台文字颜色 22 BOOL SetConsoleColor(WORD wAttributes) 23 { 24 HANDLE hHandle = GetStdHandle(STD_OUTPUT_HANDLE); 25 if (hHandle == INVALID_HANDLE_VALUE) 26 { 27 cout << "GetStdHandle Error!" << endl; 28 return false; 29 } 30 //SetConsoleTitle(L"读者写者问题"); 31 return SetConsoleTextAttribute(hHandle, wAttributes); 32 } 33 34 void PrintWriterLog(string strLog) 35 { 36 EnterCriticalSection(&g_csStdout); 37 SetConsoleColor(FOREGROUND_GREEN); 38 cout << strLog << endl; 39 SetConsoleColor(FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED); 40 LeaveCriticalSection(&g_csStdout); 41 } 42 unsigned int WINAPI WriterThreadFunc(PVOID pParam) 43 { 44 volatile int nCnt = 0; 45 while(nCnt++ < 5) 46 { 47 PrintWriterLog("写者线程等待中... "); 48 49 EnterCriticalSection(&g_csReaderWriter); 50 WaitForSingleObject(g_EventNoReader, INFINITE); 51 //标记写者正在写文件 52 ResetEvent(g_EventNoWriter); 53 54 PrintWriterLog("写者开始写文件 "); 55 //do something--writing file 56 57 Sleep(rand()%100); 58 PrintWriterLog("写者结束写文件 "); 59 60 SetEvent(g_EventNoWriter); 61 62 //因为g_EventNoReader是自动复位用以防止出现多个写线程同时写的情况,但是写线程退出时应将此信号重新改为触发 63 SetEvent(g_EventNoReader); 64 65 LeaveCriticalSection(&g_csReaderWriter); 66 67 Sleep(2000); 68 } 69 70 return 0; 71 } 72 73 void PrintReaderLog(string strFormat, ...) 74 { 75 va_list va; 76 va_start(va, strFormat); 77 EnterCriticalSection(&g_csStdout); 78 SetConsoleColor(FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED); 79 vfprintf_s(stdout, strFormat.c_str(), va); 80 LeaveCriticalSection(&g_csStdout); 81 va_end(va); 82 } 83 unsigned int WINAPI ReaderThreadFunc(PVOID pParam) 84 { 85 PrintReaderLog("读者线程[%d]等待中... ", GetCurrentThreadId()); 86 WaitForSingleObject(g_EventNoWriter, INFINITE); 87 EnterCriticalSection(&g_csReaderCnt); 88 ++g_nCurrentReaderCnt; 89 if (g_nCurrentReaderCnt == 1) 90 {//g_csReaderWriter防止在未改变g_EventNoReader为未触发状态之前,写线程获得信号,此时会出现同时读写的情况 91 EnterCriticalSection(&g_csReaderWriter); 92 ResetEvent(g_EventNoReader); 93 LeaveCriticalSection(&g_csReaderWriter); 94 } 95 LeaveCriticalSection(&g_csReaderCnt); 96 97 PrintReaderLog("读者线程[%d]开始读文件 ", GetCurrentThreadId()); 98 //do something---reading file 99 Sleep(rand()%100); 100 PrintReaderLog("读者线程[%d]结束读文件 ", GetCurrentThreadId()); 101 102 EnterCriticalSection(&g_csReaderCnt); 103 --g_nCurrentReaderCnt; 104 if (g_nCurrentReaderCnt == 0) 105 SetEvent(g_EventNoReader); 106 LeaveCriticalSection(&g_csReaderCnt); 107 108 return 0; 109 } 110 111 int main() 112 { 113 HANDLE hThread[READER_NUM+1]; 114 g_EventNoWriter = CreateEvent(NULL, false, true, NULL); 115 g_EventNoReader = CreateEvent(NULL, true, true, NULL); 116 InitializeCriticalSection(&g_csReaderCnt); 117 InitializeCriticalSection(&g_csStdout); 118 InitializeCriticalSection(&g_csReaderWriter); 119 cout << " 读者写者问题" << endl << endl; 120 121 //先启两个读线程 122 for (int i = 1; i <= 2; ++i) 123 hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFunc, NULL, 0, NULL); 124 //启动一个写线程 125 hThread[0] = (HANDLE)_beginthreadex(NULL, 0, WriterThreadFunc, NULL, 0, NULL); 126 Sleep(50); 127 //启动其他读线程 128 for (int i = 3; i <= READER_NUM; ++i) 129 hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFunc, NULL, 0, NULL); 130 131 WaitForMultipleObjects(READER_NUM+1, hThread, true, INFINITE); 132 133 for (int i = 0; i <= READER_NUM+1; ++i) 134 CloseHandle(hThread[i]); 135 CloseHandle(g_EventNoWriter); 136 CloseHandle(g_EventNoReader); 137 DeleteCriticalSection(&g_csStdout); 138 DeleteCriticalSection(&g_csReaderCnt); 139 DeleteCriticalSection(&g_csReaderWriter); 140 141 return 0; 142 }
解法二:读写锁SRWLock
注意事项:一个线程仅能锁定资源一次,不能多次锁定资源。
1 #include <iostream> 2 #include <string> 3 #include <Windows.h> 4 #include <process.h> 5 using namespace std; 6 7 /************************************************************************************ 8 9 读写锁SRWLock---模拟读者写者问题:1个写者,5个读者 10 11 *************************************************************************************/ 12 13 CRITICAL_SECTION g_csStdout; 14 SRWLOCK g_srwLock; //读写锁 15 const int READER_NUM = 5; //读者个数 16 17 18 //设置控制台文字颜色 19 BOOL SetConsoleColor(WORD wAttributes) 20 { 21 HANDLE hHandle = GetStdHandle(STD_OUTPUT_HANDLE); 22 if (hHandle == INVALID_HANDLE_VALUE) 23 { 24 cout << "GetStdHandle Error!" << endl; 25 return false; 26 } 27 //SetConsoleTitle(L"读者写者问题"); 28 return SetConsoleTextAttribute(hHandle, wAttributes); 29 } 30 31 void PrintWriterLog(string strLog) 32 { 33 EnterCriticalSection(&g_csStdout); 34 SetConsoleColor(FOREGROUND_GREEN); 35 cout << strLog << endl; 36 SetConsoleColor(FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED); 37 LeaveCriticalSection(&g_csStdout); 38 } 39 unsigned int WINAPI WriterThreadFunc(PVOID pParam) 40 { 41 volatile int nCnt = 0; 42 while(nCnt++ < 5) 43 { 44 PrintWriterLog("写者线程等待中... "); 45 //申请写文件排它锁 46 AcquireSRWLockExclusive(&g_srwLock); 47 48 PrintWriterLog("写者开始写文件 "); 49 //do something--writing file 50 Sleep(rand()%100); 51 52 53 PrintWriterLog("写者结束写文件 "); 54 //释放锁 55 ReleaseSRWLockExclusive(&g_srwLock); 56 Sleep(2000); 57 } 58 59 return 0; 60 } 61 62 void PrintReaderLog(string strFormat, ...) 63 { 64 va_list va; 65 va_start(va, strFormat); 66 EnterCriticalSection(&g_csStdout); 67 SetConsoleColor(FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED); 68 vfprintf_s(stdout, strFormat.c_str(), va); 69 LeaveCriticalSection(&g_csStdout); 70 va_end(va); 71 } 72 unsigned int WINAPI ReaderThreadFunc(PVOID pParam) 73 { 74 PrintReaderLog("读者线程[%d]等待中... ", GetCurrentThreadId()); 75 //读者申请读取文件 76 AcquireSRWLockShared(&g_srwLock); 77 78 PrintReaderLog("读者线程[%d]开始读文件 ", GetCurrentThreadId()); 79 //do something---reading file 80 Sleep(rand()%100); 81 82 PrintReaderLog("读者线程[%d]结束读文件 ", GetCurrentThreadId()); 83 //释放读取锁 84 ReleaseSRWLockShared(&g_srwLock); 85 return 0; 86 } 87 88 int main() 89 { 90 HANDLE hThread[READER_NUM+1]; 91 92 InitializeCriticalSection(&g_csStdout); 93 InitializeSRWLock(&g_srwLock); 94 cout << " 读者写者问题---读写锁SRWLock" << endl << endl; 95 96 //先启两个读线程 97 for (int i = 1; i <= 2; ++i) 98 hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFunc, NULL, 0, NULL); 99 //启动一个写线程 100 hThread[0] = (HANDLE)_beginthreadex(NULL, 0, WriterThreadFunc, NULL, 0, NULL); 101 Sleep(50); 102 //启动其他读线程 103 for (int i = 3; i <= READER_NUM; ++i) 104 hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFunc, NULL, 0, NULL); 105 106 WaitForMultipleObjects(READER_NUM+1, hThread, true, INFINITE); 107 108 for (int i = 0; i <= READER_NUM+1; ++i) 109 CloseHandle(hThread[i]); 110 111 DeleteCriticalSection(&g_csStdout); 112 113 return 0; 114 }