c++11 details of std::thread

  • 2020-06-15 09:51:46
  • OfStack

std::thread c++11 is a new thread standard library introduced by c. Through it, it is convenient to write multithreaded programs that are independent of the platform. Although customized multithreaded library for the platform will achieve the maximum performance, it will lose portability. Finally in c++11 to recognize the standard of multithreading, it can be said gratifying!!

In the use of std::thread There are two operations on the created thread: wait/detach, i.e join/detach Operation. join() Operation is in std::thread t(func) After "some" appropriate place to call, its role is to reclaim the corresponding created thread resources, to avoid causing the leak of resources. detach() Operation is in std::thread t(func) Called immediately after, to separate the thread being created from the thread doing the create action, the detached thread becomes a background thread, and the created thread "dies" regardless of the thread doing the create action, and its resources are removed init Process recycling.

Here is the main pair join Make a thorough understanding.

Due to the join Is to wait for the end of the created thread and reclaim its resources. Therefore, the location of the call to join is critical. For example, the following call locations are all wrong.


void test()
{
}

bool do_other_things()
{
}

int main()
{
  std::thread t(test);
  int ret = do_other_things();
  if(ret == ERROR) {
    return -1;
  }

  t.join();
  return 0;
}

Obviously, if std::thread0 The function call goes back to ERROR, and it exits main函数 , join is not called, so thread t's resources are not recycled, causing a resource leak.

Example 2:


void test()
{
}

bool do_other_things()
{
}

int main()
{
  std::thread t(test);

  try {
    do_other_things();
  }
  catch(...) {
    throw;
  }
  t.join();
  return 0;
}

This example is similar to example 1, if you call std::thread0 The function throws an exception, which terminates the program directly, join It will not be called, resulting in the resource not being recycled.

Then directly in the exception capture catch Call in a block of code join Will be ok.

Example 3:


void test()
{
}

bool do_other_things()
{
}

int main()
{
  std::thread t(test);

  try {
    do_other_things();
  }
  catch(...) {
    t.join();
    throw;
  }
  t.join();
  return 0;
}

Is that what a lot of people do? It's not foolproof, try/catch Blocks can only catch lightweight exception errors, in this case if invoked std::thread0 When a serious exception error occurs, then catch No catch exception is triggered, causing the program to trace back directly from the function call stack, and no call to join , will also cause thread resources have not been recycled, resources leak.

So here's a way to create a local object, take advantage of the function call stack, and make sure the destructor is triggered when the object is destroyed to make sure it's called before the main thread ends join() , waiting to reclaim the resources of the created thread.


class mythread {
private:
  std::thread &m_t;

public:
  explicit mythread(std::thread &t):m_t(t){}
  ~mythread() {
    if(t.joinable()) {
      t.join()
    }
  }

  mythread(mythread const&) = delete;
  mythread& operate=(mythread const&) = delete;
}

void test()
{
}

bool do_other_things()
{
}

int main()
{
  std::thread t(test);
  mythread q(t);

  if(do_other_things()) {
    return -1;
  }

  return 0;
}

In the above example, regardless of the call std::thread0 It was an error that caused it return main Because of the function call stack, the destructor of the local object q is always backtraced, and the destructor of q is determined first j.joinable() because join An operation can only be called once for the same thread, otherwise an error will occur. This ensures that thread 1 is waiting to be reclaimed before the main function ends.


Related articles: