多线程同步中的读者写者问题-windows 平台实现

前一段时间在项目开发中遇到了经典的读者写者问题,这里给出简单的程序实现。

程序中用了一个互斥体 Mutex 和一个信号量 Semaphore, 当然也可以使用

两个信号量。

1: ReaderWriterLock.h, 该文件定义了读写锁的类

#ifndef ReaderWriterLock_H
#define ReaderWriterLock_H

class ReaderWriterLock
{
protected:
       HANDLE readMutex;
       HANDLE writeSemaph;
       int numReaders;

public:
       ReaderWriterLock()
       {
              numReaders = 0;

              // create 1 Mutex and 1 Semaphore
              // 2 Semaphore also OK
              readMutex = CreateMutex(NULL, false, NULL);
              writeSemaph = CreateSemaphore(NULL, 1, 1, NULL);
              if (readMutex == NULL || writeSemaph == NULL)
              {
                     MessageBox(NULL, "create mutex failed!" , NULL, 0);
              }
       }

       ~ReaderWriterLock()
       {
              CloseHandle(readMutex);
              CloseHandle(writeSemaph);
       }

       inline void ReaderLock()
       {
              // lock readMutex for readers to access numReaders
              WaitForSingleObject(readMutex, INFINITE);
              numReaders++;
              if (numReaders == 1)
              {
                     // for first reader, lock writeSemaph
                     WaitForSingleObject(writeSemaph, INFINITE);
              }
              ReleaseMutex(readMutex);
       }

       inline void ReaderUnLock()
       {
              // lock readMutex for readers to access numReaders
              WaitForSingleObject(readMutex, INFINITE);
              numReaders--;
              if (numReaders == 0)
              {
                     // for last reader, unlock writeSemaph
                     ReleaseSemaphore(writeSemaph, 1, NULL);
              }
              ReleaseMutex(readMutex);
       }

       inline void WriterLock()
       {
              // lock writeSemaph for writers to access shared object
              WaitForSingleObject(writeSemaph, INFINITE);
       }

       inline void WriterUnLock()
       {
              // unlock writeSemaph for writers to access shared object
              ReleaseSemaphore(writeSemaph, 1, NULL);
       }
};

#endif

2:ReaderWriter.cpp, 该文件是测试程序,在 VC++6 中调试通过

// ReaderWriter.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

#include <process.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

#include "ReaderWriterLock.h"

char sharedStr[128]="this is a shared string !";
char logFile[128]="d:\\log.txt";
ReaderWriterLock* rwLock=new ReaderWriterLock();

void readerProc(void* param);
void writerProc(void* param);
void WriteLogStr(char* s);

using namespace std;

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
        // TODO: Place code here.
       int readerId;
       int writerId;
       FILE* f;

       // clear the log
       f = fopen(logFile, "w");
       fclose(f);

       //rwLock = new ReaderWriterLock();
       srand(time(0));

       readerId = 1;
       _beginthread(readerProc, 0, (void*)&readerId);
       Sleep(10);

       writerId = 1;
       _beginthread(writerProc, 0, (void*)&writerId);
       Sleep(10);

       readerId = 2;
       _beginthread(readerProc, 0, (void*)&readerId);
       Sleep(10);

       writerId = 2;
       _beginthread(writerProc, 0, (void*)&writerId);
       Sleep(10);

       readerId = 3;
       _beginthread(readerProc, 0, (void*)&readerId);

       // running for 5s
       Sleep(5000);

       return 0;
}

void readerProc(void* param)
{
       int myid;
       char idStr[128];
       char str[128];

       myid = *((int*)(param));
       itoa(myid, idStr, 10);

       strcpy(str, "reader ");
       strncat(str, idStr, 128);
       strcat(str, " begin......");

       //cout << "reader " << myid << " begin......" << endl;
       WriteLogStr(str);

       while (true)
       {
              // first sleep a random time : between 1 - 5 s
              int sleepTime; 
              sleepTime = 1 + (int)(5.0*rand()/(RAND_MAX+1.0)); 
              Sleep(sleepTime*10);

              // prepare str
              strcpy(str, "reader ");
              strncat(str, idStr, 128);
              strcat(str, " is reading the shared string :    ");

              // then access the shared var
              rwLock->ReaderLock();
              strncat(str, sharedStr, 128);
              rwLock->ReaderUnLock();

              //cout << "reader " << myid << " is reading the shared string : " << sharedStr << endl;
              WriteLogStr(str);
       }      
}

void writerProc(void* param)
{
       int myid;
       char idStr[128];
       char str[128];

       myid = *((int*)(param));
       itoa(myid, idStr, 10);

       strcpy(str, "writer ");
       strncat(str, idStr, 128);
       strcat(str, " begin......");

       //cout << "reader " << myid << " begin......" << endl;
       WriteLogStr(str);

       while (true)
       {
              // get a random char
              int randChar; 
              randChar = myid + (int)(5.0*rand()/(RAND_MAX+1.0)); 
              randChar += 40;

              // then access the shared var
              rwLock->WriterLock();
               for (int i=0; i<20; i++)
               {
                      sharedStr[i] = randChar;
                      Sleep(1);
               }
               sharedStr[20] = 0; // append a '\0' to end a string

               strcpy(str, "writer ");
               strncat(str, idStr, 128);
               strcat(str, " is writing the shared string to : ");
               strncat(str, sharedStr, 128);
              rwLock->WriterUnLock();

              //cout << "reader " << myid << " is reading the shared string : " << sharedStr << endl;
              WriteLogStr(str);
       }
}

void WriteLogStr(char* s)
{
       FILE* f;

       f = fopen(logFile, "a");
       if (f != NULL)
       {
              fwrite(s, strlen(s), 1, f);
              fwrite("\n", 1, 1, f);
       }

       fclose(f);
}

posted @ 2009-05-29 20:21  coding_rabbit  阅读(418)  评论(0编辑  收藏  举报