> Java > java지도 시간 > 본문

Boost::io_service 해석

坏嘻嘻
풀어 주다: 2018-09-14 09:32:17
원래의
1992명이 탐색했습니다.

io_servie는 작업이 void(void) 함수인 작업 대기열을 구현합니다. Io_servie의 가장 일반적으로 사용되는 두 가지 인터페이스는 post와 run입니다. Post는 작업을 작업 대기열에 전달합니다. Run은 모든 작업이 실행될 때까지 대기열에 있는 작업을 실행하며, run은 N 스레드에 의해 호출될 수 있습니다. Io_service는 완전히 스레드로부터 안전한 대기열입니다.

boost::io_service 해석

asio는 Boost에서 제공하는 C++ 비동기 프로그래밍 모델 라이브러리입니다. 핵심 클래스 io_service는 다중 스레드 프로그래밍에서 작업 대기열 및 작업 배포를 제공합니다. , 주로 소켓 및 io 프로그래밍의 이벤트 드라이버(완료 포트, 선택, 폴, epoll 등)로 사용됩니다.

Queue 모델

각 io_service에는 공개 작업 대기열과 여러 개인 작업 대기열이 있으며, 공개 대기열은 각 스레드에서 공유되며 개인 대기열은 공유됩니다. 각 스레드마다 고유한 스레드가 있습니다.

Boost::io_service 해석

io_service의 작업 실행 과정은 대략 다음과 같습니다.

  1. 실행 호출 메소드를 입력하고 메인 루프에 들어갑니다.

  2. 공개 대기열이 비어 있지 않은지 확인하고 작업 수만큼 실행합니다. 1보다 크면 다른 유휴 스레드가 동시에 활성화됩니다.
  3. 작업 실행이 완료된 후 각 스레드의 비공개 팀에 있는 작업을 다음으로 이동합니다. 공개 작업 대기열
  4. 트리거 리액터 , Linux에서는 일반적으로 epoll이 사용되며 해당 이벤트의 작업은 개인 대기열에 배치됩니다. .
  5. 큐가 비어 있으면 유휴 스레드 큐에 현재 스레드를 추가하고 동시에 대기 상태로 들어가 다른 스레드가 깨어날 때까지 대기합니다( 작업_작업).
  6. 사용자가 post를 호출하면 작업이 공개 대기열 op_queue로 직접 전달됩니다.
  7. 스레드 풀 모델

일반적으로 사용되는 두 가지 스레드 풀 모델이 있습니다.

하나는 다중 스레드입니다. 작업 큐는 공유됩니다. 사용자는 작업 큐에 작업을 제출하고 다른 스레드는 큐에서 작업 실행을 얻기 위해 경쟁합니다. 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();
}
로그인 후 복사

이 스레드 풀의 병목 현상은 하나의 작업 대기열과 여러 스레드에 있다는 것을 쉽게 알 수 있습니다. 스레드 작업 경쟁은 대규모 동시 프로그램에서 쉽게 성능 저하로 이어질 수 있습니다.

다른 하나는 사용자가 작업 대기열 중 하나에 작업을 무작위로 또는 순환적으로 전달하도록 선택할 수 있다는 것입니다. 작업 대기열의 작업은 스레드에 의해서만 할당될 수 있습니다. 소비가 위치한 곳입니다. 이러한 종류의 스레드 풀에는 부스트 예제에도 해당 구현(io_service_pool)이 있습니다. 기본 방법은 각각 스레드에 해당하는 여러 io_service 개체를 만드는 것입니다.

#🎜 🎜#

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에서는 일부 클래스의 정의가 다르기 때문입니다.

io_service는 기본 인터페이스를 정의하고 Linux에서의 구현은 task_io_service입니다.

Boost::io_service 해석task_io_service는 주로 세 가지를 정의합니다.

리액터는 완료 포트, 선택, 폴, epoll 등과 같은 이벤트 드라이버입니다. on ;

  1. 사용자가 게시한 작업과 리액터에서 반환한 작업을 저장하는 데 사용되는 공개 작업 대기열 op_queue; 🎜🎜#스레드 관련 변수. io_service 자체는 스레드를 생성하지 않지만 스레드 개인 큐 등과 같은 일부 스레드 호출 정보를 저장합니다.

  2. 또한 task_io_service는 유휴 스레드 목록도 유지하고 추가 작업이 도착하면 유휴 스레드 중 하나를 깨웁니다. 일반적인 Linux 단일 작업 대기열 스레드 풀에서는 조건 변수를 사용하여 스레드를 깨웁니다. 멀티 코어 시스템에서 pthread_cond_signal 호출은 대기 상태에 있는 하나 이상의 스레드를 깨웁니다(https://linux 참조). .die.net/man/3/pthread_cond_signal) 작업이 하나뿐이지만 유휴 스레드 방식을 사용하면 작업이 있을 때 하나의 유휴 스레드만 깨어나므로 불필요한 깨우기를 많이 줄일 수 있습니다.

  3. thread_info_base 클래스는 메모리 1개만으로 간단한 메모리 풀을 유지하므로 지속적으로 메모리 해제를 신청하는 경우에만 메모리 할당 오버헤드를 줄일 수 있습니다.
  4. io_service::work의 역할: io_service::run은 작업이 완료되면 즉시 반환됩니다. 이는 상주 서비스 프로그램을 작성할 때 원하는 것이 아닙니다. Boost에서 제공하는 솔루션은 다음과 같습니다. a 얼핏 보면 work 변수가 놀랍습니다. io_server와는 전혀 관련이 없을 것 같은 이 변수는 실제로 실행의 동작을 제어할 수 있습니다. 소스 코드를 열어보면 놀라울 정도로 작업 구현이 간단하다는 것을 알 수 있습니다. 생성자에서 io_service의 works_started() 메서드를 호출하여 대기 중인 작업(++outstanding_work_) 수가 0보다 큽니다. 이런 식으로 io_service::run은 항상 처리할 작업이 있다고 생각합니다. 그리고 돌아오지 않을 것이다.

  5. 관련 추천:

Angular 업데이트 directive_AngularJS

서비스 상태에 따라

AngularJS_AngularJS에서 팩토리와 서비스를 이용하는 방법 소개

위 내용은 Boost::io_service 해석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿