转发,请保持地址:http://blog.csdn.net/stalendp/article/details/9310171
以前学习过Java的多线程设计,出于对java多线程设计的熟悉,我把pthread的多线程方法按照java的习惯封装了一下,并写了几个例子,分享一下。
// ThreadHelper.h
#ifndef threadTest_ThreadHelper_h
#define threadTest_ThreadHelper_h
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
void msleep(unsigned sec) {
usleep(sec*1000);
}
// 参考 http://stackoverflow.com/questions/1151582/pthread-function-from-a-class
class Thread {
protected:
std::string name;
pthread_t mythread;
pthread_mutex_t mymutex;
pthread_cond_t mycond;
protected:
virtual void* run() = 0;
public:
Thread() {
pthread_mutex_init(&mymutex, NULL);
pthread_cond_init(&mycond, NULL);
char msg[50];
sprintf(msg, "%ld", time(NULL));
name = msg;
}
Thread(const char* _name) : name(_name) {
pthread_mutex_init(&mymutex, NULL);
pthread_cond_init(&mycond, NULL);
}
virtual ~Thread() {
pthread_mutex_destroy(&mymutex);
pthread_cond_destroy(&mycond);
}
const char* getName() {
return name.c_str();
}
void start() {
if ( pthread_create( &mythread, NULL, _run, this) ) {
printf("error creating thread.");
abort();
}
}
private:
static void* _run(void* This) {
return ((Thread*) This)->run();
}
};
class Synchronizable {
protected:
pthread_mutex_t mymutex;
pthread_cond_t mycond;
public:
#define LOCK_BEGIN pthread_mutex_lock(&mymutex)
#define LOCK_END pthread_mutex_unlock(&mymutex)
#define WAIT pthread_cond_wait(&mycond, &mymutex)
#define NOTIFY_ALL pthread_cond_broadcast(&mycond);
public:
Synchronizable() {
pthread_mutex_init(&mymutex, NULL);
pthread_cond_init(&mycond, NULL);
}
virtual ~Synchronizable() {
pthread_mutex_destroy(&mymutex);
pthread_cond_destroy(&mycond);
}
};
#endif
然后给出一个生产消费者模式的例子:
#ifndef threadTest_PtProducerConsumer_h
#define threadTest_PtProducerConsumer_h
#include "ThreadHelper.h"
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <string>
#include <vector>
#include <sstream>
// 生产者必须将数据安全地交给消费者。虽然只是这样的问题,但当生产者与消费者
// 在不同的线程上运行时,两者的处理速度差将是最大的问题。当消费者要取数据时
// 生产者还没有建立出数据,或是生产者建立出数据时消费者的状态还没办法接受数据等。
// Producer-Consumer Pattern是在生产者和消费者之间加入一个“桥梁参与者”。
// 以这个桥梁参与者缓冲线程之间的处理速度差。
class Table : Synchronizable {
private:
int tail, head, count;
std::vector<std::string> buffer;
public:
Table(int _count) : tail(0), head(0), count(0) {
buffer.resize(_count);
}
void put(const char* cake) {
LOCK_BEGIN;
while (count >= buffer.size()) {
printf("!!!TABLE IS FULL!!!\n");
fflush(stdout); // flush stdout for windows
WAIT;
}
buffer[tail] = cake;
tail = (tail+1) % buffer.size();
count++;
NOTIFY_ALL;
printf("puts %s -- size %d\n", cake, count);
fflush(stdout);
LOCK_END;
}
const char* take() {
LOCK_BEGIN;
while (count<=0) {
printf("!!!NO MORE CAKES!!!\n");
WAIT;
}
std::string cake = buffer[head];
head = (head+1) % buffer.size();
count--;
NOTIFY_ALL;
printf("takes %s -- size %d\n", cake.c_str(), count);
fflush(stdout);
LOCK_END;
return cake.c_str();
}
};
static int mid;
class MakerThread: public Thread {
private:
Table* table;
public:
MakerThread(const char* _name, Table* _table) : Thread(_name) {
this->table = _table;
srand((unsigned)time(NULL));
}
void* run() {
while (true) {
msleep(rand()%1000);
std::stringstream ss;
ss << "[Cake No." << nextId() << " by " << getName() << "]";
table->put(ss.str().c_str());
}
return NULL;
}
static int nextId() {
return mid++;
}
};
class EaterThread: public Thread {
private:
Table* table;
public:
EaterThread(const char* _name, Table* _table) : Thread(_name) {
this->table = _table;
}
void* run() {
while (true) {
const char* cake = table->take();
// printf("%s\n", cake);
msleep(rand()%1000);
}
return NULL;
}
};
void pcRun() {
Table* table = new Table(3); // 建立可以放置3个蛋糕的桌子
(new MakerThread("MakerThread-1", table))->start();
(new MakerThread("MakerThread-2", table))->start();
(new MakerThread("MakerThread-3", table))->start();
(new EaterThread("EaterThread-1", table))->start();
(new EaterThread("EaterThread-2", table))->start();
(new EaterThread("EaterThread-3", table))->start();
msleep(90 * 1000);
getchar();
printf("hello producer consumer");
}
#endif
读写锁 (未完成)
#include "ThreadHelper.h"
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <string>
#include <vector>
#include <sstream>
/*
当线程“读取”实例的状态时,实例的状态不会变化。会使实例状态变化的,只有线程对线程“写入”
的操作而已。把视点放在实例状态变化的角度来看时,“读取”与“写入”本身时不同的东西。
Read-Write Lock Pattern将读取与写入分开来处理。在读取数据之前,必须获取用来读取
的锁定。而要写入的时候,则必须获取用来写入的锁定。
因为进行读取时,实例的状态不会改变,所以,就算有多个线程在同时读取也没有关系。但,有人
在读取的时候,不可以做写入的操作。
写入的时候,实例的状态就会改变。于是,当有一个线程在写入的时候,其他线程就不可以有进行
读取和写入。
一般来说,进行共享互斥会时线程性能变差,但将写入的共享互斥与读取的共享互斥分开来考虑,
就可以提升成效的性能。
*/
class ReadWriteLock : public Synchronizable {
private:
int readingReaders, waitingWriters, writingWriters;
bool preferWriter;
public:
void readLock() {
while (writingWriters>0 || (preferWriter&&waitingWriters>0) ) {
WAIT;
}
readingReaders++;
}
void readUnlock() {
readingReaders--;
preferWriter = true;
NOTIFY_ALL;
}
void writeLock() {
waitingWriters++;
while (readingReaders>0 || writingWriters>0) {
WAIT;
}
waitingWriters--;
writingWriters++;
}
void writeUnlock() {
writingWriters--;
preferWriter = false;
NOTIFY_ALL;
}
};
class Data {
private:
std::string buffer;
ReadWriteLock* lock;
public:
Data(int size) {
buffer.resize(size, '*');
lock = new ReadWriteLock();
}
virtual ~Data() {
delete lock;
}
char* read() {
lock->readLock();
char* rt = doRead();
lock->readUnlock();
return rt;
}
void write(char c) {
lock->writeLock();
doWrite(c);
lock->writeUnlock();
}
char* doRead() {
return NULL;
}
void doWrite(char c) {
}
void slowly() {
msleep(50);
}
};
class WriterThread: public Thread {
private:
Data* data;
std::string filler;
int index;
public:
WriterThread(Data* _data, const char* _filler) : data(_data), filler(_filler), index(0) {
}
void* run() {
while (true) {
char c = nextchar();
data->write(c);
msleep(rand()%3000);
}
return NULL;
}
char nextchar() {
char c = filler.at(index);
index++;
if (index>=filler.size()) {
index = 0;
}
return c;
}
};
class ReaderThread: public Thread {
private:
Data* data;
public:
ReaderThread(Data* _data) : data(_data) {
}
void* run() {
while (true) {
char* readbuf = data->read();
printf("reads %s\n", readbuf);
}
return NULL;
}
};
void rwlRun() {
Data* data = new Data(10);
(new ReaderThread(data))->start();
(new ReaderThread(data))->start();
(new ReaderThread(data))->start();
(new ReaderThread(data))->start();
(new ReaderThread(data))->start();
(new ReaderThread(data))->start();
(new WriterThread(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))->start();
(new WriterThread(data, "abcdefghijklmnopqrstuvwxyz"))->start();
printf("hello read write lock\n");
}
#endif
参考:《Java多线程设计模式详解》
相关文章: http://blog.csdn.net/stalendp/article/details/9253665