網站首頁 編程語言 正文
一、可擴展性和多線程
基于 Boost.Asio 之類的庫開發程序與通常的 C++ 風格不同。可能需要更長時間才能返回的函數不再按順序調用。 Boost.Asio 不調用阻塞函數,而是啟動異步操作。操作完成后應該調用的函數現在在相應的處理程序中調用。這種方法的缺點是順序執行函數的物理分離,這會使代碼更難理解。
諸如 Boost.Asio 之類的庫通常用于實現更高的效率。無需等待操作完成,程序可以在其間執行其他任務。因此,可以啟動多個同時執行的異步操作——請記住,異步操作通常用于訪問進程之外的資源。由于這些資源可以是不同的設備,它們可以獨立工作并同時執行操作。
可擴展性描述了程序有效地從額外資源中受益的能力。借助 Boost.Asio,可以從外部設備同時執行操作的能力中受益。如果使用線程,則可以在可用的 CPU 內核上同時執行多個功能。 Boost.Asio 的線程提高了可伸縮性,因為您的程序可以利用內部和外部設備,這些設備可以獨立執行操作或相互協作執行操作。
如果在 boost::asio::io_service 類型的對象上調用成員函數 run(),則在同一線程中調用關聯的處理程序。通過使用多個線程,程序可以多次調用 run()。一旦異步操作完成,I/O 服務對象將在這些線程之一中執行處理程序。如果第二個操作在第一個操作之后不久完成,則 I/O 服務對象可以在不同的線程中執行處理程序。現在,不僅進程外的操作可以并發執行,進程內的處理程序也可以并發執行。
二、線程示例
示例 32.3。 I/O 服務對象的兩個線程同時執行處理程序
#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
#include <chrono>
#include <thread>
#include <iostream>
using namespace boost::asio;
int main()
{
io_service ioservice;
steady_timer timer1{ioservice, std::chrono::seconds{3}};
timer1.async_wait([](const boost::system::error_code &ec)
{ std::cout << "3 sec\n"; });
steady_timer timer2{ioservice, std::chrono::seconds{3}};
timer2.async_wait([](const boost::system::error_code &ec)
{ std::cout << "3 sec\n"; });
std::thread thread1{[&ioservice](){ ioservice.run(); }};
std::thread thread2{[&ioservice](){ ioservice.run(); }};
thread1.join();
thread2.join();
}
前面的示例已在示例 32.3 中轉換為多線程程序。使用 std::thread,在 main() 中創建了兩個線程。在每個線程中的唯一 I/O 服務對象上調用 run()。這使得 I/O 服務對象可以在異步操作完成時使用兩個線程來執行處理程序。
在示例 32.3 中,兩個鬧鐘都應在三秒后響起。因為有兩個線程可用,所以兩個 lambda 函數可以同時執行。如果在執行第一個鬧鐘的處理程序時第二個鬧鐘響起,則可以在第二個線程中執行該處理程序。如果第一個鬧鐘的handler已經返回,I/O服務對象可以使用任意線程執行第二個handler。
當然,使用線程并不總是有意義的。示例 32.3 可能不會將消息按順序寫入標準輸出流。相反,它們可能會混淆。兩個處理程序可能同時在兩個線程中運行,共享全局資源 std::cout。為避免中斷,需要同步對 std::cout 的訪問。如果處理程序不能同時執行,線程的優勢就喪失了。
示例 32.4。兩個 I/O 服務對象各有一個線程并發執行處理程序
#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
#include <chrono>
#include <thread>
#include <iostream>
using namespace boost::asio;
int main()
{
io_service ioservice1;
io_service ioservice2;
steady_timer timer1{ioservice1, std::chrono::seconds{3}};
timer1.async_wait([](const boost::system::error_code &ec)
{ std::cout << "3 sec\n"; });
steady_timer timer2{ioservice2, std::chrono::seconds{3}};
timer2.async_wait([](const boost::system::error_code &ec)
{ std::cout << "3 sec\n"; });
std::thread thread1{[&ioservice1](){ ioservice1.run(); }};
std::thread thread2{[&ioservice2](){ ioservice2.run(); }};
thread1.join();
thread2.join();
}
對單個 I/O 服務對象重復調用 run() 是使基于 Boost.Asio 的程序更具可擴展性的推薦方法。但是,您也可以創建多個 I/O 服務對象,而不是為一個 I/O 服務對象提供多個線程。
在示例 32.4 中,兩個 I/O 服務對象在兩個類型為 boost::asio::steady_timer 的鬧鐘旁邊使用。該程序基于兩個線程,每個線程綁定到另一個 I/O 服務對象。兩個 I/O 對象 timer1 和 timer2 不再綁定到同一個 I/O 服務對象。它們綁定到不同的對象。
示例 32.4 的工作方式與之前相同。無法就何時使用多個 I/O 服務對象提供一般性建議。因為 boost::asio::io_service 代表一個操作系統接口,所以任何決定都取決于特定的接口。
在 Windows 上,boost::asio::io_service 通常基于 IOCP,在 Linux 上,它基于 epoll()。擁有多個 I/O 服務對象意味著將使用多個 I/O 完成端口,或者將多次調用 epoll()。這是否比僅使用一個 I/O 完成端口或一次調用 epoll() 更好取決于具體情況。
原文鏈接:https://yamagota.blog.csdn.net/article/details/127584039
相關推薦
- 2023-03-21 redis哨兵模式說明與搭建詳解_Redis
- 2022-08-04 Python使用RPC例子_python
- 2023-07-14 express token的一個用法
- 2022-10-01 使用flask如何獲取post請求參數_python
- 2022-04-12 如何解決git上傳文件出錯 [rejected] cjp -> cjp (fetch first)e
- 2022-03-31 Python的三個重要函數詳解_python
- 2022-08-10 詳細聊一聊algorithm中的排序算法_C 語言
- 2022-05-28 python中數組和列表的簡單實例_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支