2015-12-04 3 views
1

Там есть пример кода:станд :: нить пожалуйста, объясните выход

class MY_Timer 
    { 
    // ... 
    void start(const UInt timeOut, const UInt events, CALLBACK_TARGET reciever) 
     { 
      cout << __FUNCTION__ << " " << timerName << endl; 

      if (active) return; 
      if ((0u == timeOut) || (0u == events)) return; 
      if (nullptr == reciever) return; 

      interval = timeOut; 
      eventsAmount = events; 
      active = true; 
      cb_target = reciever; 

      thread clockieThread(&MY_Timer::clockie, this); // комментарий 
      clockieThread.join(); 
     }; 

    private: 
     void clockie() 
     { 
      while (eventsAmount--) 
      { 
      Sleep(interval); 
      cb_target(timerName, eventsAmount); 
      } 

      active = false; 
     } 
    // ... 
    }; 

    void target(const char * timerName, const UInt data) 
    { 
     cout << timerName << " DATA: " << data << endl; 
    } 

    int main() 
    { 
     MY_Timer * tOne = new MY_Timer("ALPHA"); 
     MY_Timer * tTwo = new MY_Timer("OMEGA"); 

     tOne->start(200, 10, &target); 
     tTwo->start(300, 20, &target); 
    } 

Это то, что выход выглядит следующим образом:

MY_Timer::start ALPHA 
ALPHA DATA: 9 
ALPHA DATA: 8 
ALPHA DATA: 7 
ALPHA DATA: 6 
ALPHA DATA: 5 
ALPHA DATA: 4 
ALPHA DATA: 3 
ALPHA DATA: 2 
ALPHA DATA: 1 
ALPHA DATA: 0 
MY_Timer::start OMEGA 
OMEGA DATA: 9 
OMEGA DATA: 8 
OMEGA DATA: 7 
OMEGA DATA: 6 
OMEGA DATA: 5 
OMEGA DATA: 4 
OMEGA DATA: 3 
OMEGA DATA: 2 
OMEGA DATA: 1 
OMEGA DATA: 0 

Не могли бы вы объяснить, почему это поведение кода как есть только один поток выполнения. Я думал, что выход будет смешиваться с сообщениями из двух потоков, например, если я буду делать это:

void foo(const char * name, int interval) 
{ 
    int step = 10; 
    while (step--) 
    { 
     Sleep(interval); 
     cout << name << " step: " << step << endl; 
    } 
} 

int main() 
{ 
    thread t1(foo, "ALPHA", 200); 
    thread t2(foo, "OMEGA", 300); 
    t1.join(); 
    t2.join(); 

    return 0; 
} 

И результат будет, как: «OMG, Многопоточность»:

ALPHA step: 9 
    OMEGA step: 9 
    ALPHA step: 8 
    OMEGA step: 8 
    ALPHA step: 7 
    ALPHA step: 6 
    OMEGA step: 7 
    ALPHA step: 5 
    OMEGA step: 6 
    ALPHA step: 4 
    ALPHA step: 3 
    OMEGA step: 5 
    ALPHA step: 2 
    OMEGA step: 4 
    ALPHA step: 1 
    ALPHA step: 0 
    OMEGA step: 3 
    OMEGA step: 2 
    OMEGA step: 1 
    OMEGA step: 0 

Спасибо!

+4

Вы начинаете тему, а затем сразу начинаете «присоединяться», я не уверен, чего вы ожидали. – user657267

+0

Вызов o'death: 'clockieThread.join();' –

ответ

0

Как сказал комментатор, «join()» блокирует основной поток до тех пор, пока ваш недавно порожденный поток не закончит завершение, поэтому, когда вы вызываете свою функцию «start», он создает поток, а затем ждет его завершения.

 thread clockieThread(&MY_Timer::clockie, this); // комментарий 
     clockieThread.join(); 

Вы можете использовать «СТД :: Thread :: отрываться», чтобы позволить закончить нить сама по себе, - но вы не сможете следить за потоками, которые вы делаете это.

2

Это преступник:

 thread clockieThread(&MY_Timer::clockie, this); // комментарий 
     clockieThread.join(); 

Если вы думаете о том, что это делает, и расширить свой код, то результат будет выглядеть немного так:

int main() 
{ 
    MY_Timer * tOne = new MY_Timer("ALPHA"); 
    MY_Timer * tTwo = new MY_Timer("OMEGA"); 

    tOne->start(200, 10, &target); 
    // clockieThread1 created 
    // clockieThread1 joined (blocks until complete) 
    tTwo->start(300, 20, &target); 
    // clockieThread2 created 
    // clockieThread2 joined (blocks until complete) 

    return 0; 
} 

Вы присоединяетесь нить сразу после его создания, и поэтому он блокирует все, пока поток не завершится.

Возможно, вы хотите, чтобы поток был членом класса, и вы можете запустить его/присоединиться к нему.

class MY_Timer 
{ 
    thread clockieThread; 
    ... 
    void start(const UInt timeOut, const UInt events, CALLBACK_TARGET reciever) 
    ... 
    clockieThread = thread(&MY_Timer::clockie, this); 
    // Remove the clockieThread.join() here 
    } 

    void join() { 
    clockieThread.join(); 
    } 
} 

Затем с этим изменением, вы можете сделать следующее:

int main() 
{ 
    MY_Timer * tOne = new MY_Timer("ALPHA"); 
    MY_Timer * tTwo = new MY_Timer("OMEGA"); 

    tOne->start(200, 10, &target); 
    tTwo->start(300, 20, &target); 
    tOne->join(); 
    tTwo->join(); 

    return 0; 
} 

Если вы хотите, чтобы устранить tOne->join() звонки полностью, хотя, вы могли бы сделать присоединиться внутри деструктора для класса:

class MY_Timer 
{ 
    ... 
    ~MY_Timer() { 
    clockieThread.join(); 
    } 
} 
Смежные вопросы