目录
队列模型
线程池模型
首页 Java java教程 boost::io_service解读

boost::io_service解读

Sep 14, 2018 am 09:32 AM

io_servie 实现了一个任务队列,这里的任务就是void(void)的函数。Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,run是执行队列中的任务,直到全部执行完毕,并且run可以被N个线程调用。Io_service是完全线程安全的队列。

boost::io_service解读

asio是boost提供的一个c++异步编程模型库,其核心类io_service,在多线程编程里面提供了任务队列和任务分发功能,在socket、io编程里主要作为一个事件驱动器(完成端口、select、poll、epoll等)。

队列模型

每个io_service都一个公有任务队列,和多个私有任务队列,公有队列由各个线程共享,私有队列则是每个线程独享一个。

20161126162556488.png

io_service的任务执行流程大致如下:

  1. 调用run方法,进入主loop;

  2. 判断公有队列是否为空,不为空则取出任务并执行,当任务数大于1时同时唤醒其他空闲线程;

  3. 任务执行结束,把各个线程的私有队里面的任务移动到公有任务队列里面;

  4. 触发reactor,linux下面一般是epoll,当有事件时,把相应的事件的任务放到私有队列里。

  5. 当队列为空时,把当前线程加到空闲线程队列里面,同时进入wait状态,等待其他线程的唤醒(task_operation)。

  6. 当用户调用post时,任务是直接投递到公有队列op_queue里面。

线程池模型

常用的线程池模型有两种:

一种是多个线程共享一个任务队列,用户把任务投递到该任务队列中,其他线程竞争从该队列中获取任务执行。结合boost::thread,在多个线程里面调用run方法,即可实现该线程池:

using namespace boost;
using namespace boost::asio;
io_service ios;
int thread_num = 10;
thread *t[thread_num] = {0};
// 创建线程池
for(int i = 0; i < thread_num; ++i)
{
    t[i] = new thread(bind(&io_service::run, &ios));
}

// 向任务队列中投递任务,该任务将随机由一个调用run方法的线程执行
ios.post(func);

// 等待线程退出
for(int i = 0; i < thread_num; ++i)
{
    t[i]->join();
}
登录后复制

很容易看出来,这种线程池的瓶颈在于一个任务队列,多个线程竞争取任务,在大并发的程序里面容易导致性能下降。

另一种是每个线程各自维护一个任务队列,用户可以选择随机或者轮训地投递任务到其中一个任务队列里面,该任务队列中的任务只由其所在的线程才能消费。这种线程池在boost的example里面也有相应的实现(io_service_pool),基本方法是创建多个io_service对象,每个对应一个thread,代码如下:

using namespace boost;
using namespace boost::asio;
int thread_num = 10;
io_service ios[thread_num];
thread *t[thread_num] = {0};
// 创建线程池
for(int i = 0; i < thread_num; ++i)
{
    t[i] = new thread(bind(&io_service::run, &ios[i]));
}

// 轮训投递任务
for(int i = 0; i < thread_num; ++i)
{
    ios[i].post(func);
}   

// 等待线程退出
for(int i = 0; i < thread_num; ++i)
{
    t[i]->join();
}
登录后复制

以下是基于linux环境作的类图,因为在windows上,有些类有不同的定义。

20161126162639332.png

io_service定义了主要的接口,在linux下的实现是task_io_service。

task_io_service主要定义了三个东西:

  1. 一个reactor,reactor就是完成端口、select、poll、epoll之类的事件驱动器;

  2. 一个公共的任务队列op_queue,用来存放用户post的任务,和reactor返回的任务;

  3. 线程相关变量。io_service本身不会创建任何线程,但它会保存一些线程调用信息,如线程私有队列等。

此外,task_io_service还维护了一个空闲线程列表,在有多余任务到来时,唤醒其中一个空闲线程。在常见的linux单任务队列的线程池里面,用一个condition变量来唤醒线程,在多核系统里面,一次pthread_cond_signal调用,会唤起处于wait状态的一个或多个线程(参考https://linux.die.net/man/3/pthread_cond_signal),尽管只有一个任务,如果采用空闲线程的方法,有任务时只唤醒一个空闲线程,可以减少很多不必要唤醒。

thread_info_base类维护了一个简单的内存池,只有一块内存,仅在连续的申请释放内存情况下,可以减少内存开辟的开销。

io_service::work的作用:io_service::run在任务执行完毕时会立刻返回,这个并不是编写常驻服务的程序所想要的,boost给的解决方案是定义一个work变量,乍看很神奇,这个跟io_server似乎没有任何关系的变量竟然能控制run的行为,打开源码一看,work的实现简单的出奇,它仅仅是在构造函数里调用io_service的worked_started()方法,使其待处理任务数(++outstanding_work_)大于0,如此,io_service::run就认为一直有任务待处理而不返回了。

相关推荐:

Angular 根据 service 的状态更新 directive_AngularJS

简介AngularJS中使用factory和service的方法_AngularJS

 

以上是boost::io_service解读的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Java 中的平方根 Java 中的平方根 Aug 30, 2024 pm 04:26 PM

Java 中的平方根指南。下面我们分别通过例子和代码实现来讨论平方根在Java中的工作原理。

Java 中的完美数 Java 中的完美数 Aug 30, 2024 pm 04:28 PM

Java 完美数指南。这里我们讨论定义,如何在 Java 中检查完美数?,示例和代码实现。

Java 中的随机数生成器 Java 中的随机数生成器 Aug 30, 2024 pm 04:27 PM

Java 随机数生成器指南。在这里,我们通过示例讨论 Java 中的函数,并通过示例讨论两个不同的生成器。

Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

Java 版 Weka 指南。这里我们通过示例讨论简介、如何使用weka java、平台类型和优点。

Java 中的阿姆斯特朗数 Java 中的阿姆斯特朗数 Aug 30, 2024 pm 04:26 PM

Java 中的阿姆斯特朗数指南。这里我们讨论一下java中阿姆斯特朗数的介绍以及一些代码。

Java 中的史密斯数 Java 中的史密斯数 Aug 30, 2024 pm 04:28 PM

Java 史密斯数指南。这里我们讨论定义,如何在Java中检查史密斯号?带有代码实现的示例。

Java Spring 面试题 Java Spring 面试题 Aug 30, 2024 pm 04:29 PM

在本文中,我们保留了最常被问到的 Java Spring 面试问题及其详细答案。这样你就可以顺利通过面试。

突破或从Java 8流返回? 突破或从Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一种强大且表达力丰富的处理数据集合的方式。然而,使用Stream时,一个常见问题是:如何从forEach操作中中断或返回? 传统循环允许提前中断或返回,但Stream的forEach方法并不直接支持这种方式。本文将解释原因,并探讨在Stream处理系统中实现提前终止的替代方法。 延伸阅读: Java Stream API改进 理解Stream forEach forEach方法是一个终端操作,它对Stream中的每个元素执行一个操作。它的设计意图是处

See all articles