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