• 读者写者问题


    参考地址: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 }
  • 相关阅读:
    PHP读取MySQL中文乱码
    dotnet如何使用资源文件
    常见的隐藏地址的流媒体下载方法(转)
    圣诞礼物:Google Maps API开发样例一则
    Google EarthMapsKML核心开发技术揭秘 一个完整的Google Maps应用
    WEB界面测试用例~ 收藏
    通过xmlhttp实现报告归档
    转换长日期为短日期
    做delphi控件的笔记
    Reflector使用手记
  • 原文地址:https://www.cnblogs.com/dongsheng/p/5086623.html
Copyright © 2020-2023  润新知