多线程笔记2

转发,请保持地址: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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值