2017-11-26 1 views
-2

난 그냥 내 자신에게 물어 : 코드에 스레드 풀을 만들 때
코드를 컴파일
컴파일 된 코드가 각 스레드에 대한 복사본을 가지고 있습니까? 내가 매크로 기능을 사용하고
컴파일 시간 동안 확장이 매크로입니다, 스레드에 전달하면스레드는 컴파일 또는 런타임 중에 결정됩니까?

가와 "내가 무슨 생각"또는시 런타임,
을 그리고 컴파일시에있는 경우 왜 다음 코드 필요 뮤텍스 : 오직 주 스레드는 이미 람다 함수를 만들어의 작업을 이미 만든 큐에 작동 실행 다음 스레드를
을 io_service하는 스레드를 게시 될 것입니다하지만 여기

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/date_time.hpp> 
#include <iostream> 
namespace asio = boost::asio; 
#define PRINT_ARGS(msg) do {\ 
boost::lock_guard<boost::mutex> lg(mtx); \ 
std::cout << '[' << boost::this_thread::get_id() \ 
<< "] " << msg << std::endl; \ 
} while (0) 
int main() { 
asio::io_service service; 
boost::mutex mtx; 

for (int i = 0; i < 20; ++i) { 
service.post([i, &mtx]() { 
PRINT_ARGS("Handler[" << i << "]"); 
boost::this_thread::sleep(
boost::posix_time::seconds(1)); 
}); 
} 

boost::thread_group pool; 
for (int i = 0; i < 4; ++i) { 
pool.create_thread([&service]() { service.run(); }); 
} 
pool.join_all(); 
} 

가 lock_guard가, cout을 임계 영역을 >>> > 뮤텍스가 필요 없다고 생각하게 만들었습니까?
이 생각인가요? 여기

내가 컴파일 중에 매크로 확장을 시뮬레이션합니다

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/date_time.hpp> 
#include <iostream> 
namespace asio = boost::asio; 


#define PRINT_ARGS(msg) do {\ 
boost::lock_guard<boost::mutex> lg(mtx); \ 
std::cout << '[' << boost::this_thread::get_id() \ 
<< "] " << msg << std::endl; \ 
} while (0) 

int main() { 
asio::io_service service; 
boost::mutex mtx; 

for (int i = 0; i < 20; ++i) { 
service.post([i, &mtx]() { 

//PRINT_ARGS("Handler[" << i << "]");//>>>>>this will be 

do {\\ 
boost::lock_guard<boost::mutex> lg(mtx); \\ 
std::cout << '[' << boost::this_thread::get_id() \\ 
<< "] " << "Handler[" << i << "]" << std::endl; \\ 
} while (0) 

boost::this_thread::sleep(
boost::posix_time::seconds(1)); 
}); 
} 

boost::thread_group pool; 
for (int i = 0; i < 4; ++i) { 
pool.create_thread([&service]() { service.run(); }); 
} 
pool.join_all(); 
} 

를 다음 프로그램은 다음과 같은 순서에있을 것입니다 :
1 주 스레드 : io_service 예를
2 주 스레드를합니다 수 있도록 뮤텍스 인스턴스
3 개의 메인 스레드 : 메인 스레드가이 코드를 가지고있는 책에 정의 된 "람다 함수"를 io_service의 내부 큐에 추가 할 때마다 루프를 20 번 반복한다.
내 질문은 입니다. : 주 스레드가 큐에 20 개의 람다 함수 객체를 추가합니까?이 경우 각각의 값은 i
이고 새로운 4 개의 스레드가 작업을 시작하면 동일한 책에 따라 스레드 기능 "실행"을 제공합니다 함수 하나씩 객체를 제거하고이 경우 하나
하나씩 실행한다
쓰레드 (1) : 삭제 (λ1) 및 고유에 개별 인스턴스로서 자신의 코드를 실행하는 I
실 2 : 삭제 (λ2) 및 자체 코드를 고유 한 i와 별도의 인스턴스로 실행합니다.
스레드 3 : 람다 3을 제거하고 고유 코드를 사용하여 고유 한 코드로 실행합니다.
스레드 4 : 람다 제거 4 고유 한 코드로 별도의 인스턴스로 실행하십시오
다음은 스레드 1 againget lambda 5
이것은 큐에 람다 함수로 20 개의 함수 객체가 있습니다. "wrapper의 somesort로 래핑 될 수 있습니다" 따라서 각 스레드는 별도의 객체를 가져 오며 이런 이유로 컴파일 후에 "20 개의 내부 어셈블리 코드"가 필요하지 않습니다.

그러나 큐의 작업이 " , 동시에 2 개의 스레드가 중요한 코드에 동시에 액세스하는 것을 막기 위해 뮤텍스가 필요합니다.
어떤 시나리오가 현재 코드 기호로 표시됩니까?

답변

0

매크로는 항상 컴파일 타임에 확장되지만 컴파일러는 스레드에 대한 초보적인 지식 만 가지고 있습니다 (주로 특정 변수가 스레드 로컬이라는 것을 말합니다).

코드는 실제로 실행되는 디스크상의 이미지 또는 메모리 내 사본에 한 번만 존재하게됩니다.

PRINT_ARGS에서 뮤텍스를 잠그면 각 작업의 메시지가 다른 스레드에 의해 중단되지 않고 전체적으로 인쇄됩니다. (그렇지 않으면 작업을 시작하여 해당 메시지를 인쇄하고 메시지를 인쇄하는 다른 스레드에서 다른 작업을 중단 한 다음 첫 번째 작업 메시지의 나머지 부분을 인쇄 할 수 있습니다).

+0

나는 매크로 이름을 확장하기 위해 코드를 편집했는데 뮤텍스가 여전히 대기열에있는 람다 함수 안에 있고 스레드에 주어진 실행 함수가 람다 함수가 아니라는 것을 알았습니다 ..... 그렇다면 왜 우리는 1 개의 람다를 대표하는 각각 20 개의 작업이 있다면 뮤텍스가 필요합니다 –

+0

뮤텍스가 작업이 아니라 여기에 있다고 생각합니까? –

+0

예, 뮤텍스는 출력이 혼합되지 않도록 유지합니다. 람다는 주변 컨텍스트로부터 뮤텍스를 캡쳐하고 있으므로 실제로 뮤텍스가 하나만 있다는 것을 기억하십시오 (많은 참조가 있습니다). – SoronelHaetir