参考地址: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("写者线程等待中...\n");
 48 
 49         EnterCriticalSection(&g_csReaderWriter);
 50         WaitForSingleObject(g_EventNoReader, INFINITE);
 51         //标记写者正在写文件
 52         ResetEvent(g_EventNoWriter);
 53 
 54         PrintWriterLog("写者开始写文件\n");
 55         //do something--writing file
 56 
 57         Sleep(rand()%100);
 58         PrintWriterLog("写者结束写文件\n");
 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]等待中...\n", 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]开始读文件\n", GetCurrentThreadId());
 98     //do something---reading file
 99     Sleep(rand()%100);
100     PrintReaderLog("读者线程[%d]结束读文件\n", 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 << "\t\t读者写者问题" << 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("写者线程等待中...\n");
 45         //申请写文件排它锁
 46         AcquireSRWLockExclusive(&g_srwLock);
 47         
 48         PrintWriterLog("写者开始写文件\n");
 49         //do something--writing file
 50         Sleep(rand()%100);
 51 
 52         
 53         PrintWriterLog("写者结束写文件\n");
 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]等待中...\n", GetCurrentThreadId());
 75     //读者申请读取文件
 76     AcquireSRWLockShared(&g_srwLock);
 77     
 78     PrintReaderLog("读者线程[%d]开始读文件\n", GetCurrentThreadId());
 79     //do something---reading file
 80     Sleep(rand()%100);
 81     
 82     PrintReaderLog("读者线程[%d]结束读文件\n", 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 << "\t\t读者写者问题---读写锁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 }

 

posted on 2015-12-29 18:12  可笑痴狂  阅读(6276)  评论(0编辑  收藏  举报