简体   繁体   English

std :: thread请解释输出

[英]std::thread please explain output

There is a code sample: 有一个代码示例:

  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);
    }

This is what output is looks like: 输出结果如下所示:

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

Could you please explain why this code behaviour is like there is only one execution flow. 您能否解释一下为什么这种代码行为就像只有一个执行流程。 I thought output will be mixed with messages from two threads, like if I will do this: 我认为输出将与来自两个线程的消息混合在一起,就像我将要做的那样:

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;
}

And output will be like: "OMG, MULTITHREADING!": 输出将是:“ OMG,MULTITHREADING!”:

 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

Thank you! 谢谢!

This is the culprit: 这是罪魁祸首:

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

If you think about what this does, and expand your code, the result would look a bit like this: 如果您考虑这样做,然后扩展代码,结果将看起来像这样:

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;
}

You are joining the thread immediately after creating it, and so it blocks everything until the thread finishes. 创建线程后,您将立即加入该线程,因此它将阻塞所有线程,直到线程完成。

What you probably want is to have the thread be a member of the class, and you can start/join it. 您可能希望使线程成为该类的成员,然后可以启动/加入该线程。

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();
  }
}

Then with that change, you can do the following: 然后进行更改,您可以执行以下操作:

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;
}

If you want to eliminate the tOne->join() calls entirely though, you could do the join inside the destructor for the class: 如果您想完全消除tOne->join()调用,则可以在该类的析构函数内进行tOne->join()

class MY_Timer
{
  ...
  ~MY_Timer() {
    clockieThread.join();
  }
}

As the commentator said, "join()" blocks the main thread until your newly spawned thread has finished completing, so when you call your "start" function - it creates the thread then waits for it to finish. 正如评论员所说,“ join()”会阻塞主线程,直到您新生成的线程完成为止,因此,当您调用“ start”函数时,它将创建线程,然后等待线程完成。

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

You can use "std::thread::detach" to let the thread finish on its own - but you won't be able to keep track of threads you do this to. 您可以使用“ std :: thread :: detach”让线程自己完成-但您将无法跟踪执行此操作的线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM