多線程同步中的讀者寫者問題 - linux 平臺實現

linux 平臺下的實現與 windows 很相似,只有一些代碼上的小的差別。

1: ReaderWriterLock.h, 該文件定義了讀寫鎖的類

#ifndef ReaderWriterLock_H
#define ReaderWriterLock_H

#include <bits/pthreadtypes.h>
#include <semaphore.h>

class ReaderWriterLock
{
protected:
 pthread_mutex_t readMutex;
 sem_t writeSemaph;
 int numReaders;

public:
 ReaderWriterLock()
 {
  numReaders = 0;

  // create 1 Mutex and 1 Semaphore
  // 2 Semaphore also OK
  pthread_mutex_init(&readMutex, NULL);
  sem_init(&writeSemaph, 0, 1);
 }

 ~ReaderWriterLock()
 {
     pthread_mutex_destroy(&readMutex);
            sem_destroy(&writeSemaph);
 }
 inline void ReaderLock()
 {
  // lock readMutex for readers to access numReaders
  pthread_mutex_lock(&readMutex);
  numReaders++;
  if (1 == numReaders)
  {
   // for first reader, lock writeSemaph
   sem_wait(&writeSemaph);
  }
  pthread_mutex_unlock(&readMutex);
 }

 inline void ReaderUnLock()
 {
  // lock readMutex for readers to access numReaders
  pthread_mutex_lock(&readMutex);
  numReaders--;
  if (numReaders == 0)
  {
   // for last reader, unlock writeSemaph
   sem_post(&writeSemaph);
  }
  pthread_mutex_unlock(&readMutex);
 }

 inline void WriterLock()
 {
  // lock writeSemaph for writers to access shared object
  sem_wait(&writeSemaph);
 }

 inline void WriterUnLock()
 {
  // unlock writeSemaph for writers to access shared object
  sem_post(&writeSemaph);
 }
};


#endif

2:ReaderWriter.cpp, 該文件是測試程序,在 Linux 上調試通過

#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#include "ReaderWriterLock.h"
#include "RasUtil.h"

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

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

int main(int argc, char* argv[])
{
 int ret;
 pthread_t reader1;
 pthread_t reader2;
 pthread_t reader3;
 pthread_t writer1;
 pthread_t writer2;
 int readerId;
 int writerId;
 FILE* f;

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

 // init random seed
 srand(getpid());

 readerId = 1;
 pthread_create(&reader1, NULL, readerProc, (void*)(&readerId));
 sleep(1);

 writerId = 1;
 pthread_create(&writer1, NULL, writerProc, (void*)&writerId);
        sleep(1);

 readerId = 2;
 pthread_create(&reader2, NULL, readerProc, (void*)&readerId);
 sleep(1);

 writerId = 2;
 pthread_create(&writer2, NULL, writerProc, (void*)&writerId);
 sleep(1);

 readerId = 3;
 pthread_create(&reader3, NULL, readerProc, (void*)&readerId);

 sleep(5);

 return 0;
}

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

 myid = *((int*)(param));
 RasUtil::intToStr(myid, idStr);

 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)); 
  usleep(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));
 RasUtil::intToStr(myid, idStr);

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

 cout << "writer " << 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;
    usleep(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 << "writer " << myid << " is writing the shared string to : " << 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);
}

3:RasUtil.h,完成整數轉換爲字符串

#ifndef _RasUtil_h_
#define _RasUtil_h_

class RasUtil
{
public:
 static inline void intToStr(int i, char* str);


};


inline void RasUtil::intToStr(int i, char* str)
{
    int dec;
    int sign;
    char* p;

    p = ecvt(i, 10, &dec, &sign);
    strcpy(str, p);
    str[dec] = 0;
}

#endif


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章