Explain C++ thread in detail

  • 2020-10-23 21:07:26
  • OfStack

1, introduction,

C++11 is added < thread > The header file that primarily declares the std::thread thread class. std::thread, the standard class of C++11, encapsulates threads and defines some classes representing threads, classes and methods for mutually exclusive access in C++11. Apply std::thread in C++11 to facilitate multithreaded program shift values.

std::thread class member function:

(1), get_id: Gets thread ID and returns an object of type std::thread::id.

(2) joinable: Check whether the thread can be join. Check whether the thread object identifies a viable thread for one activity (active). thread objects constructed by default, thread objects that have completed join, and thread objects that have completed detach are not joinable.

(3) join: Calling this function will block the current thread. Block the thread in which the caller (caller) resides until the thread identified by the std::thread object of join has finished executing.

(4) detach: Separate the execution instance represented by the current thread object from the thread object, so that the execution of the thread can be carried out separately. Once the thread finishes executing, its allocated resources will be released.

(5), native_handle: This function returns a thread handle related to the specific implementation of std::thread. native_handle_type is the bridge between thread class and SDK API. For example, in Linux g++(libstdc++), native_handle_type is pthread_t type in pthread. When the function of thread class cannot meet our requirements (such as changing the priority of a thread), The associated pthread function can be called to the directory with the return value of native_handle() for an instance of the thread class as an argument. This member function is only present in class thread if the library implementation supports it. If present, it returns a value used to access implementation-specific information associated to the thread.

(6) swap: Exchange the underlying handle represented by the two thread objects.

(7), operator= : moves the thread object

(8) hardware_concurrency: static member function that returns the maximum number of concurrent threads on the current computer. You can basically view it as the number of cores in the processor.

In addition, std: : thread: : thread ID id said, defined in the operating system at runtime only able to identify the thread identifier, and at the same time indicating identified its value to the state of the thread. Values of this type are returned by thread::get_id and this_thread::get_id to identify threads.

Sometimes we need to operate on the current caller thread in the thread execution code. For this, C++11 has one namespace defined specifically, this_thread, which is also declared in the < thread > In the header file, which includes the get_id() function used to get the current caller thread; yield() function can be used to jump out of the running state of the caller thread and return it to the operating system for scheduling. In other words, the current thread abandons execution and the operating system schedules another thread to continue execution. The sleep_until() function will sleep until a specified time (time point) before the thread is reawakened. The sleep_for() function is to sleep a thread for a specified time slice (time span) before the thread is reawakened, but due to thread scheduling and other reasons, the actual sleep may actually be longer than the time slice indicated by sleep_duration.

1. Create 1 thread

It is relatively simple to create a thread. Using std's thread to instantiate one thread object, the creation is completed. Example:


#include <iostream>
#include <thread>
#include <stdlib.h> //sleep
 
using namespace std;
 
void t1() // A normal function used to execute a thread 
{
  for (int i = 0; i < 10; ++i)
  {
    cout << "t1111\n";
    sleep(1);
  }
}
void t2()
{
  for (int i = 0; i < 20; ++i)
  {
    cout << "t22222\n";
    sleep(1);
  }
}
int main()
{
  thread th1(t1); // instantiation 1 Thread objects th1 , using the function t1 Construct, and the thread begins to execute ( t1() ) 
  thread th2(t2);
 
  th1.join(); //  You must thread join or detach  Wait for the child thread to terminate before the main process can exit 
  th2.join(); 
 
  //or use detach
  //th1.detach();
  //th2.detach();
 
  cout << "here is main\n\n";
 
  return 0;
}

The above mentioned problem, you can also use detach, detach is used, and thread object separation, this thread can be executed independently, but since there is no such thread object to this thread and lost control of it, when a thread object destructor will continue to perform in the background, but when the main program exit does not guarantee thread can be performed. If you do not have a good control mechanism or this background thread is important, it is best to use join instead of detach.

2, mutex and std:: use of lock_guard

The header file is #include < mutex > mutex is used to guarantee thread synchronization and prevent different threads from operating on the same data.

However, lock_guard is relatively safe. It is scope-based and self-unlocking. When the object is created, it acquires a mutex like m.lock ()1, and at the end of its life cycle, it automatically destructs (unlock) without causing one thread to exit unexpectedly. Example:


#include <iostream>
#include <thread>
#include <mutex>
#include <stdlib.h>
 
int cnt = 20;
std::mutex m;
void t1()
{
  while (cnt > 0)
  {  
    std::lock_guard<std::mutex> lockGuard(m);
    // std::m.lock();
    if (cnt > 0)
    {
      //sleep(1);
      --cnt;
      std::cout << cnt << std::endl;
    }
    // std::m.unlock();
    
  }
}
void t2()
{
  while (cnt > 0)
  {
    std::lock_guard<std::mutex> lockGuard(m);
    // std::m.lock();
    if (cnt > 0)
    {
      --cnt;
      std::cout << cnt << std::endl;
    }
    // std::m.unlock();
  }
}
 
int main(void)
{
 std::thread th1(t1);
 std::thread th2(t2);
 
 th1.join();  // Waiting for the t1 exit 
 th2.join();  // Waiting for the t2 exit 
 
 std::cout << "here is the main()" << std::endl;
 
 return 0;
}

The output of cnt is decreasing in order, not out of order due to multithreading:...

[

19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
here is the main()

]

Related articles: