一个基于信号量的简易线程池

转载自:一个基于信号量的简易线程池


信号无需由同一个线程来获取和释放,因此信号可用于异步事件通知,如用于信号处理程序中。同时,由于信号包含状态,因此可以异步方式使用,而不用象条件变量那样要求获取互斥锁。但是,信号的效率不如互斥锁高。缺省情况下,如果有多个线程正在等待信号,则解除阻塞的顺序是不确定的。信号在使用前必须先初始化,但是信号没有属性。计数信号量与互斥锁一起使用时的功能几乎与条件变量一样强大。在许多情况下,使用计数信号量实现的代码比使用条件变量实现的代码更为简单。本文参考:1、Linux多线程编程-信号量的使用2、Linux C++ 一个线程池的简单实现


CThread.h

#ifndef CTHREAD_H_
#define CTHREAD_H_

#include 

class CThread {
private:
    pthread_t m_thread; //保持线程句柄
public:
    CThread(void* (*threadFuction)(void*),void* threadArgv);
    virtual ~CThread();

    void JoinThread();
};

#endif /* CTHREAD_H_ */

CThread.cpp

#include "CThread.h"

CThread::CThread(void* (*threadFuction)(void*),void* threadArgv) {

    // 初始化线程属性
    pthread_attr_t threadAttr;
    pthread_attr_init(&threadAttr);

    pthread_create(&m_thread, &threadAttr, threadFuction, threadArgv);
}

CThread::~CThread() {
    // TODO Auto-generated destructor stub
}


void CThread::JoinThread()
{
    // join
    pthread_join(m_thread, NULL);
}

CThreadManager.h

#ifndef CTHREADMANAGER_H_
#define CTHREADMANAGER_H_

#include 
#include 
#include 
#include 

#include "CThread.h"

using namespace std;

class CThreadManager {
    friend void* ManageFuction(void*);
private:
    sem_t m_sem;    // 信号量
    pthread_mutex_t m_mutex; // 互斥锁

    queue m_queWork; // 工作队列
    list m_lstThread; // 线程list

    int (*m_threadFuction)(int); //函数指针,指向main函数传过来的线程执行函数


public:
    CThreadManager(int (*threadFuction)(int), int nMaxThreadCnt);
    virtual ~CThreadManager();

    int WaitSem();

    int PostSem();

    int LockMutex();

    int UnlockMutex();

    void PushWorkQue(int nWork);

    int PopWorkQue();

    int RunThreadFunction(int nWork);
};

#endif /* CTHREADMANAGER_H_ */

CThreadManager.cpp

#include "CThreadManager.h"

// 线程执行函数,它只是个壳子,处理信号量和互斥锁等,
// 最后调用main函数传过来的线程执行函数来实现业务处理
void* ManageFuction(void* argv)
{
    CThreadManager* pManager = (CThreadManager*)argv;

    // 进行无限循环(意味着线程是不销毁的,重复利用)
    while(true)
    {
        // 线程开启后,就在这里阻塞着,直到main函数设置了信号量
        pManager->WaitSem();
        printf("thread wakeup.\n");

        // 从工作队列中取出要处理的数
        pManager->LockMutex();
        int nWork = pManager->PopWorkQue();
        pManager->UnlockMutex();

        printf("call Count function.\n");
        pManager->RunThreadFunction(nWork);
    }

    return 0;
}


CThreadManager::CThreadManager(int (*threadFuction)(int), int nMaxThreadCnt) {

    sem_init(&m_sem, 0, 0);
    pthread_mutex_init(&m_mutex, NULL);

    m_threadFuction = threadFuction;

    for(int i=0; i::iterator it;
    for(it=m_lstThread.begin(); it!=m_lstThread.end();it++)
    {
        (*it)->JoinThread();
    }
}

// 等待信号量
int CThreadManager::WaitSem()
{
    return sem_wait(&m_sem);
}

// 设置信号量
int CThreadManager::PostSem()
{
    return sem_post(&m_sem);
}

// 取得锁
int CThreadManager::LockMutex()
{
    int n= pthread_mutex_lock(&m_mutex);
    return n;
}

// 释放锁
int CThreadManager::UnlockMutex()
{
    return pthread_mutex_unlock(&m_mutex);
}

// 往工作队列里放要处理的数
void CThreadManager::PushWorkQue(int nWork)
{
    m_queWork.push(nWork);
}

// 从工作队列中取出要处理的数
int CThreadManager::PopWorkQue()
{
    int nWork = m_queWork.front();
    m_queWork.pop();

    return nWork;
}

// 执行main函数传过来的线程执行函数
int CThreadManager::RunThreadFunction(int nWork)
{
    return (*m_threadFuction)(nWork);
}

ThreadTest.cpp

#include 
#include 

#include "CThreadManager.h"

using namespace std;

// 线程要执行的函数
int Count(int nWork)
{
    int nResult = nWork * nWork;
    printf("count result is %d\n",nResult);

    return 0;
}

int main() {

    // 创建线程管理类的实例,把要执行的线程函数和最大线程数传进去
    CThreadManager* pManager = new CThreadManager(Count, 3);

    // 把要进行计算的数放到工作队列中
    pManager->PushWorkQue(5);
    pManager->PushWorkQue(20);

    // 设置信号量,唤醒线程
    pManager->PostSem();
    pManager->PostSem();

    // 等待子线程执行
    sleep(1);

    return 0;
}

你可能感兴趣的:(一个基于信号量的简易线程池)