2012-07-20 2 views
3

나는 멀티 스레딩에 약간 익숙하므로 이러한 질문이 너무 사소한 경우 용서해주십시오.C++ 주 스레드에서 여러 스레드 처리

내 응용 프로그램은 스레드에 여러 스레드를 만들고 각 스레드에서 작업을 수행해야합니다.

예를 들어, 50 세트의 파일을 읽고, CreateThread() 함수를 사용하여이 파일을 읽는 스레드를 만듭니다.

이제이 주 스레드는 파일에 액세스하기 위해 4 개의 스레드를 생성합니다. 첫 번째 스레드는 파일 1, 두 번째 파일 2 등이 지정됩니다.

첫 번째 스레드가 파일 읽기 1을 완료하고 주 스레드에게 필요한 데이터를 제공 한 후 주 스레드는 파일 5를 사용하여이를 호출하고 데이터를 가져와야합니다. 모든 50 개의 파일을 읽을 때까지 다른 모든 스레드에 대해서도 마찬가지입니다.

그 후, 각 스레드가 파괴되고 마지막으로 내 스레드가 파괴됩니다.

내가 직면하고 문제는 다음과 같습니다

1) 어떻게 파일 읽기 후 종료 스레드를 중지?

2) 다른 파일 이름으로 스레드를 다시 호출하는 방법은 무엇입니까?

3) 내 하위 스레드는 메인 스레드에 정보를 어떻게 제공합니까?

4) 스레드가 파일 읽기를 완료하고 주 스레드에게 데이터를 반환하면 주 스레드가 어떤 스레드가 데이터를 제공했는지 어떻게 알 수 있습니까?

감사합니다.

답변

4

이것은 멀티 스레드 프로그래밍에서 매우 일반적인 문제입니다. 이것을 생산자 - 소비자 문제로 볼 수 있습니다. 메인 스레드는 작업자 스레드 (예 : http://www.mario-konrad.ch/blog/programming/multithread/tutorial-06.html)가 "소비"하는 작업을 "생성합니다". 또한 "스레드 풀"에 관해 읽을 수도 있습니다.

부스트의 동기화 (http://www.boost.org/doc/libs/1_50_0/doc/html/thread.html)를 읽고 플랫폼 독립적이며 사용하기 좋은 부스트의 스레딩 기능을 사용하는 것이 좋습니다.

질문에 더 구체적으로 말하자면 작업을 수행 할 대기열을 생성해야합니다. 일반적으로 모든 작업자 스레드에 대해 동일한 대기열을 사용합니다. 스레드 1이 작업 1, 5, 9를 수행하는지 확실히 확인하려는 경우. .. 당신은 작업자 스레드 당 하나의 큐를 원할 수 있습니다. 이 대기열에 대한 액세스는 mutex에 의해 동기화되어야하며 대기중인 스레드는 새로운 데이터가 뮤텍스에 추가 될 때 condition_variables에 의해 알릴 수 있습니다.

1.

)는 스레드 함수를 종료하지만, 어떤 변수를 통해 상태가 소성 될 때까지 기다린 후 while ([exit condition not true]) 루프

2) 참조 1.

3)를 사용하여 다시 있지 않은 행 둘 다 액세스가 있고 (예 : 결과 대기열)

4.)에 의해 보호됩니다.이 정보를 결과 큐에 기록 된 결과로 추가합니다.

다른 조언 : 멀티 스레딩을 올바르게하는 것은 항상 어렵습니다. 가능한 한 조심스럽게 시도하고 교착 상태 및 경쟁 조건을 감지하는 테스트를 작성하십시오.

0

이런 종류의 문제에 대한 일반적인 해결책은 스레드 풀과 큐를 사용하는 것입니다. 주 스레드는 모든 파일/파일 이름을 대기열에 넣고 스레드 풀, 즉 각 스레드가 대기열에서 항목을 가져 와서 처리하는 다른 스레드를 시작합니다. 하나의 항목이 처리되면 다음 항목으로 넘어갑니다 (그때까지는 대기열이 아직 비어 있지 않은 경우). 메인 쓰레드는 큐가 비어 있고 모든 쓰레드가 종료되었을 때 모든 것이 처리된다는 것을 안다.

그래서 1)과 2)는 다소 상충됩니다. 스레드를 멈추지 않고 다시 호출하면 대기열에있는 항목이 발견되는 한 계속 실행됩니다. 3)에서는 스레드가 정보를 넣고 메인 스레드가 읽는 큐를 다시 사용할 수 있습니다. 4)에 대해 각 스레드에게 ID를 부여하고 데이터와 함께 넣을 수 있습니다. 그러나 일반적으로 주 스레드는 어떤 스레드가 정확하게 데이터를 처리했는지 알 필요가 없습니다.

//main 
for(all filenames) 
    queue.push_back(filename); 

//start some thread 
threadPool.StartThreads(4, CreateThread(queue)); 

//wait for threads to end 
threadPool.Join(); 

//thread 
class Thread 
{ 
public: 
    Thread(queue q) : q(q) {} 

    void Start(); 

    bool Join(); 

    void ThreadFun() 
    { 
    auto nextQueueItem = q.pop_back(); 
    if(!nextQueuItem) 
     return; //q empty 
    ProcessItem(nextQueueItem); 
    } 
} 
+0

은'queue'''std :: queue'입니까? 그렇다면 뮤텍스 또는 다른 잠금 메커니즘이 누락되었습니다. – Philipp

+0

그 이유는 'threadsafety에 대한 잠금'을 생략했습니다 :] – stijn

+0

죄송합니다, 죄송합니다 :-) – Philipp

0

당신이 스레드 풀을 사용하거나 파일을 읽고 당신의 synchronies을 실행할지 여부를, 그 기능이나 체인으로 귀결 :

일부 아주 기본적인 의사는 생략 threadsafety에 대한 잠금, 당신에게 아이디어를 제공합니다 직렬화 된 함수 그룹. 따라서 함수를 병렬로 실행하는 방법 (함수 당 하나의 스레드를 시작하거나 스레드 풀을 사용하여 시작하는 방법)을 찾고, 처음 네 개의 파일을 읽을 때까지 기다린 다음 큐를 사용할 수 있습니다. 여기서 읽기 스레드 결과를 밀어 넣으면 다섯 번째 함수가 대기열에서 4 개의 결과를 가져와 (비어있는 경우 대기열 차단) 처리합니다. 함수들 사이에 더 많은 의존성이 있다면, 그들 사이에 더 많은 큐를 추가 할 수 있습니다. 스케치 :

void read_file(const std::string& name, queue& q) 
{ 
    file_content f= .... // read file 
    q.push(f) 
} 

void process4files(queue& q) 
{ 
    std::vector<file_content> result; 
    for (int i = 0; i != 4; ++i) 
     result.push_back(q.pop()); 

    // now 4 files are read ... 
    assert(result.size() == 4u); 
} 

queue  q; 
thread t1(&read_file, "file1", q); 
thread t2(&read_file, "file2", q); 
thread t3(&read_file, "file3", q); 
thread t4(&read_file, "file4", q); 
thread t5(&process4files, q); 

t5.join(); 

아이디어를 얻길 바랍니다.

토르스테

관련 문제