线程池初探(NTPL/pthread)

  最近计网课设选择了写一个ftp服务器,其中我想把服务器端写成多线程部分。由此接触了posix线程及其相关部分。相关阅读书籍:【1】现代操作系统 【2】posix多线程程序设计。

  关于第二本是02年的,很久没出过新版了,NTPL与17年前的接口仍然大多一致,甚至是一样,由此引发了一些思考:现在那些花里胡哨的技术更新太快了,比如说java,c#,甚至c++每隔两年就要发布一个新的标准,然而这些底层接口仍然不变,学好了这些基础是不是更棒呢。

 

  步入正题:我最初想的线程池是弹出式的:也就是有一个请求到来,进程就为该请求创建一个线程。代码如下:

class sample
{
public:
    void process();
};

template <typename T>
class threadPool
{
public:
    threadPool();
    void append(T &s);
    static void *worker(void *s);
    ~threadPool()
    {
        if(ifDestroy==false)
        {
            destroy();
        }
    }

    void destroy()
    {
        pthread_mutex_destroy(&t);
        destroy=true;
    }

private:
    pthread_t threads[3];
    bool run = true;
    bool ifDestroy=false;
};

template <typename T>
void threadPool<T>::append(T& s)
{
    pthread_t t;
    pthread_create(&t,nullptr,worker,&s);
    pthread_detach(t);
 }

template <typename T>
threadPool<T>::threadPool()
{

} template <typename T> void *threadPool<T>::worker(void *s) { auto work= static_cast<sample *>(s); work->process(); return nullptr; } #endif //!THREAD_POOL_H

  这里我把请求的地址作为参数传入线程,并将之设置为分离的(detached)。

  关于线程的start_routine成员函数必须是静态的,这个还不清楚为什么,难道是跟c++的多态特性不兼容吗?

  这个的缺点是显而易见的:若任务很小,只需要不多的指令,那么频繁的创建和回收销毁线程的开销则是巨大的。由此引入了我的线程池的下一个版本:

  

  这回使用了mutex(mutual exclusion)互斥锁

class sample
{
public:
    void process();
};

template <typename T>
class threadPool
{
public:
    threadPool();
    void append(T &s);
    static void *worker(void *s);
    ~threadPool()
    {
        if(ifDestroy==false)
        {
            destroy();
        }
    }

    void destroy()
    {
        pthread_mutex_destroy(&t);
        destroy=true;
    }

private:
    std::queue<T *> tasks;
    pthread_t threads[3];
    bool run = true;
    pthread_mutex_t t;
    bool ifDestroy=false;
};

// template <typename T>
// void threadPool<T>::append(T& s)
// {
//     pthread_t t;
//     pthread_create(&t,nullptr,worker,&s);
//     pthread_detach(t);
// }
template <typename T>
threadPool<T>::threadPool() : tasks()
{
    pthread_mutex_init(&t, nullptr);
    for (int i = 0; i < 3; ++i)
    {
        pthread_create(&threads[i], nullptr, worker, this);
        pthread_detach(threads[i]);
    }
}

template <typename T>
void threadPool<T>::append(T &s)
{
    pthread_mutex_lock(&t);
    tasks.push(static_cast<T *>(&s));
    printf("%u append.\n", pthread_self());
    pthread_mutex_unlock(&t);
}

template <typename T>
void *threadPool<T>::worker(void *s)
{
    auto pool = static_cast<threadPool<T> *>(s);
    while (pool->run)
    {
        pthread_mutex_lock(&(pool->t));
        if(pool->tasks.empty())
        {
            pthread_mutex_unlock(&(pool->t));
       pthread_yeild();
continue; } T *work = pool->tasks.front(); pool->tasks.pop(); pthread_mutex_unlock(&(pool->t)); work->process(); } return nullptr; } #endif //!THREAD_POOL_H

  这个线程池用一个队列来先存储请求,用mutex保证其原子性(atomic),串行性。【2】的p:52说道:“互斥量的本质是在串行执行”。因为还不想涉及到条件变量和信号量,所以这里当工作线程检测到队列为空时就pthread_yield()暂时放弃cpu资源给其他线程,然而这样的不足仍有很多:比如当队列为空时,工作线程就会频繁地加锁解锁损耗计算机。【2】的p:52说到:”互斥量不是免费的。需要时间来加锁解锁。“

  

  关于信号量和条件变量,且听下回分解。

转载于:https://www.cnblogs.com/manch1n/p/10859705.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值