2013-04-12 2 views
1

우리는 두 명의 작업자가 있다고 가정합니다. 각 작업자의 신분은 01입니다. 또한 우리는 항상 작업이 도착한다고 가정 할 때 각 작업에는 어떤 작업자가이 작업을 수행해야 하는지를 지정하는 식별자 0 또는 1이 있습니다.(C/C++ Threads) : 작업을 듣고 동시에 실행하는 작업자 스레드 생성

초기에 잠긴 두 개의 스레드를 만들고 싶습니다. 두 개의 작업이 도착하면 잠금을 해제하고 각각의 작업을 수행 한 다음 다른 작업이 도착할 때까지 다시 잠급니다.

나는 다음과 같은 코드가 있습니다

#include <iostream> 
    #include <thread> 
    #include <mutex> 

    using namespace std; 

    struct job{ 

     thread jobThread; 
     mutex jobMutex; 

    }; 

    job jobs[2]; 


    void executeJob(int worker){ 

     while(true){ 

      jobs[worker].jobMutex.lock(); 

      //do some job 

     } 

    } 

    void initialize(){ 

     int i; 
     for(i=0;i<2;i++){ 
       jobs[i].jobThread = thread(executeJob, i); 
     } 

    } 

    int main(void){ 

     //initialization 
     initialize(); 

     int buffer[2]; 
     int bufferSize = 0; 

     while(true){ 
      //jobs arrive here constantly, 
      //once the buffer becomes full, 
      //we unlock the threads(workers) and they start working 
      bufferSize = 2; 
      if(bufferSize == 2){ 
       for(int i = 0; i<2; i++){ 
        jobs[i].jobMutex.unlock(); 
       } 
      } 
      break; 
    } 

    } 

내가 몇 일 전에 std::thread를 사용하기 시작하고 비주얼 스튜디오가 abort() has been called 말을 나에게 오류를 제공하는 이유하지만 난 모르겠어요. 나는 무언가가 빠진 것이 있다고 생각하지만 내 무지 때문에 나는 무엇을 알아낼 수 없다.

나는이 코드 조각 (실제로

  1. 는 두 개의 스레드를 초기화 한 후, 두 개의 스레드가 자신의 일을 할 것입니다 두 개의 스레드를 해제 메인 함수 내부에서 그들에게

  2. 를 잠 그려면을 기대

    이 경우에는 아무 것도 없음) 다시 잠기 게됩니다.

하지만 대신 오류가 발생합니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

미리 감사드립니다. cppreference's page on std::mutex::unlock에서

답변

5

이 목적으로 부스트의 스레드 풀 클래스를 사용할 수 있습니다. 효율적이고 잘 테스트되었습니다. opensource 라이브러리를 새로 작성하고 안정화하는 대신.

http://threadpool.sourceforge.net/

main() 
{ 
    pool tp(2); //number of worker threads-currently its 2. 

    // Add some tasks to the pool. 
    tp.schedule(&first_task); 
    tp.schedule(&second_task); 
} 

void first_task() 
{ 
    ... 
} 

void second_task() 
{ 
    ... 
} 

참고 : 예를 들어

제안 : 당신은 각 스레드에 대한 개별 뮤텍스 개체가 필요하지 않습니다. 단일 뮤텍스 객체 잠금 자체는 모든 스레드 간의 동기화를 수행합니다. executejob 함수에서 한 스레드의 뮤텍스를 잠그고 있고 다른 스레드를 잠금 해제하지 않고 다른 뮤텍스 객체로 잠금을 호출하면 교착 상태 또는 정의되지 않은 동작이 발생합니다.

또한 뮤텍스를 호출하기 때문에.잠금 해제하지 않고 while 루프에서 lock()을 호출하면 같은 스레드가 동일한 mutex 객체로 자물쇠를 채워 무한히 정의되지 않은 동작을하게됩니다.

스레드를 병렬로 실행할 필요가없는 경우 하나의 전역 mutex 객체를 사용하여 executejob 함수 내에서 잠금 및 잠금 해제를 사용할 수 있습니다.

mutex m; 

void executeJob(int worker) 
{ 
    m.lock(); 

    //do some job 

    m.unlock(); 
} 

이전에 제안한 것처럼 작업 병렬 사용 부스트 스레드 풀을 실행하려면.

2

:

뮤텍스가 성공적으로 파괴되기 전에 그것을 잠근 모든 스레드가 잠금을 해제해야합니다. 그렇지 않으면 동작이 정의되지 않습니다.

하나의 스레드가 다른 스레드를 대신하여 뮤텍스를 잠금 해제하는 방식이 잘못되었습니다.

시도하는 동작은 일반적으로 std::condition_variable을 사용하여 수행됩니다. 멤버 함수에 대한 링크를 보면 예제가 있습니다.

2

일반적으로 다음과 유사한 알고리즘을 작성할 수 있습니다. 그것은 pthreads와 함께 작동합니다. 나는 그것이 C++ 쓰레드에서도 잘 동작 할 것이라고 확신한다.

  1. 스레드를 만들고 condition variable에서 대기 상태로 만듭니다. work_exists.
  2. 작업이 도착하면 해당 조건 변수에서 대기중인 모든 스레드에 알립니다. 그런 다음 주 스레드에서 당신이 작업자 스레드가 일어나 work_exists 통지를 받으면 다른 조건 변수 work_done
  3. 에서 대기 시작 jobs[worker]에서 할당 된 작업을 잡고, 그들이 work_done 변수에 통지를 보내, 그것을 실행 한 다음 다시 이동 대기 상태로 work_exists 조건 변수
  4. 주 스레드가 work_done 알림을 받으면 모든 스레드가 완료되었는지 확인합니다. 그렇지 않은 경우 마지막 마무리 스레드의 알림이 도착할 때까지 대기합니다.
+0

이 간단한 예를 보여줄 수 있습니까? 불행히도 지난 시간을 찾고 있었고 내 스레드 풀을 만드는 방법에 대한 명확한 참조를 찾을 수 없었습니다. 대부분의 구현에서는 부스트를 사용합니다. 다른 제안들도 좋지만, 전에는 라이브러리를 향상시키지 않았습니다. 아마 그렇게해야 할 것 같습니다. – ksm001

관련 문제