Linux服务器开发,线程池原理与实现

本文探讨了线程池在Linux服务器开发中的作用,它解决了线程创建销毁的问题,增强了程序效率。介绍了线程池的工作原理,包括生产者消费者模型,并解析了手写线程池的实现,涉及任务优先级和多线程同步。同时,对比了nginx线程池的设计。文章总结了学习线程池的三个阶段,并预告将用C++11重写线程池。
摘要由CSDN通过智能技术生成

前言

一、线程池究竟解决了什么问题?

  • 可能第一感觉是线程池减少线程创建销毁,但是这是站在线程的角度去思考的。
  • 异步解耦的作用 主循环只做一个抛任务,写日志交给线程池,提高了程序运行效率。

注重cpu的处理能力的时候才会去粘合,注重的任务的话还是不要粘合为好。

API

  • create、init
  • push_task 返回的结果对于业务来说作用不大
  • destroy、deinit
    锦上添花的api:task_count,free_thread。

二、线程池的作用

  • 线程池是管理任务队列和工作队列的管理组件。

三、工作原理

  • 线程池并非内存池那般,从池子里面取用完归还,而是线程之间争夺资源。
  • 通过线程池的入口函数去获取任务,循环往复,再取任务再循环。
  • 生产者消费者模型:任务队列是生产者,工作队列是消费者,加锁获取资源。

四、手写线程池

  • 可以对任务进行区分,加优先级,更优秀的做法可以创建多个线程池对象。
  • 条件等待,进来时候解锁,出来加锁。
  • 当往任务队列中添加任务,应该先加锁锁住资源,中间发送条件变量的信号。
#define LL_ADD(item, list) do {     \
    item->prev = NULL;                \
    item->next = list;                \
    if(list !< NULL) list *prev =item  \
    list = item;                    \
} while(0)
  • 利用宏向链表中添加数据,这个感觉奇妙啊~
     
    while (1) {
          pthread_mutex_lock(&worker->workqueue->jobs_mtx);
          while (worker->workqueue->waiting_jobs == NULL) {
              if (worker->terminate) break;
              pthread_cond_wait(&worker->workqueue->jobs_cond, &worker->workqueue->jobs_mtx);
          }
          if (worker->terminate) {
              pthread_mutex_unlock(&worker->workqueue->jobs_mtx);
              break;}
          nJob *job = worker->workqueue->waiting_jobs;
          if (job != NULL) {
              LL_REMOVE(job, worker->workqueue->waiting_jobs);}
          pthread_mutex_unlock(&worker->workqueue->jobs_mtx);
          if (job == NULL) continue;
          job->job_function(job);
      }

  • 条件变量这块,是先解锁再加锁,King老师反复强调。不停的判断job为空,需要注意一下,担心万一被别的线程占用了怎么办。
    pthread_mutex_lock(&workqueue->jobs_mtx);
workqueue->workers = NULL;
workqueue->waiting_jobs = NULL;
pthread_cond_broadcast(&workqueue->jobs_cond);
pthread_mutex_unlock(&workqueue->jobs_mtx);
  • 通知等待着的线程,不折不扣的生产者,不过发送信号也需要加锁。防止竞争。

五、对比nginx线程池

我们的线程池为双链表,nginx的队列为什么使用二级指针。因为一级指针能指向struct ngx_thread_task_s的第一项ngx_thread_task_t *next的位置,这也正是ngx的巧妙之处。

六、总结

通过今天的学习,不仅学习到了有关线程池的知识,更重要的King老师讲述了学习的三个过程:1、逻辑想通;2、代码调通;3、对照学习。目测小生只是刚刚能做好第一步,接下来还是要付出更多的努力才能将这些知识驾驭娴熟。
这节课确实是比较轻松的,不过需要注意的是King老师在添加删除链表时使用的宏方法,这个也不是第一次见到了,希望能掌握好成为自己的东西。线程之间的条件等待也绝不是第一次听说,wait使得所有线程都爬在此处,等待任务队列中有数据,随时触发线程之前抢占资源。最后就是不停的判断job是否为空,因为担心被其他线程抢走。
在未来的时间里,我会利用C++11的std::thread函数从新改造这个线程池,希望达到异曲同工之妙。

 推荐一个 c/c++Linux后台服务器开发的经典教程给大家,个人觉得讲的不错,有兴趣的可以学习下。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值