[c++] C ++ for 루프 인쇄 잘못된 값의 스레드

C ++에서 멀티 스레딩을 이해하려고 하는데이 문제가 발생했습니다 .for 루프에서 스레드를 시작하면 잘못된 값이 인쇄됩니다. 이것은 코드입니다.

#include <iostream>
#include <list>
#include <thread>

void print_id(int id){
    printf("Hello from thread %d\n", id);
}

int main() {
    int n=5;
    std::list<std::thread> threads={};
    for(int i=0; i<n; i++ ){
        threads.emplace_back(std::thread([&](){ print_id(i); }));
    }
    for(auto& t: threads){
        t.join();
    }
    return 0;
}

나는 0,1,2,3,4 값을 인쇄 할 것으로 기대했지만 종종 같은 값을 두 번 얻었습니다. 이것은 출력입니다.

Hello from thread 2
Hello from thread 3
Hello from thread 3
Hello from thread 4
Hello from thread 5

내가 뭘 놓친거야?



답변

[&]구문 일으키는 i캡처 할 참조 . 따라서 i스레드가 실행될 때 예상보다 더 자주 진행됩니다. 더 심각하게 는 스레드가 실행되기 전에 범위를 벗어나 면 코드의 동작이 정의되지 않습니다i .

i가치에 의한 캡처 -즉 std::thread([i](){ print_id(i); })수정입니다.


답변

두 가지 문제 :

  1. 스레드가 실행될 때 제어 할 i수 없으므로 람다 의 변수 값 이 예상과 다를 수 있습니다.

  2. 변수 i는 루프와 루프에만 국한됩니다. 하나 이상의 스레드가 실행되기 전에 루프가 완료되면 해당 스레드는 수명이 종료 된 변수에 대한 유효하지 않은 참조를 갖습니다.

변수 를 참조 대신 i 으로 캡처하면 이러한 문제를 매우 간단하게 해결할 수 있습니다 . 그 수단은, 각 스레드는 것이다 복사본 값을 복사하고 각 스레드에 대해 고유 할 것이다.


답변

또 다른 한가지 :
음주 때까지 기다릴 항상 정렬 된 순서를 가질 : 0, 1, 2, 3, … 멀티 스레딩 실행 모드는 특이성이 있기 때문에 : 비결정론을 .

결정론은 동일한 조건에서 동일한 프로그램을 실행하면 다른 결과를 얻는다는 것을 의미합니다.

이는 OS가 CPU로드, 다른 프로세스의 우선 순위, 가능한 시스템 중단 등과 같은 여러 매개 변수에 따라 실행마다 스레드를 다르게 예약하기 때문입니다.

예제에는 5 개의 스레드 만 포함되어 있으므로 간단하고 스레드 수를 늘리고 처리 기능에서 절전 모드를 설정하면 결과가 실행마다 다를 수 있습니다.


답변