Blog.csdn.net/liuker888/a…

www.cnblogs.com/lidabo/p/78…

 

Knowledge links:

C++11 concurrent STD ::mutex

C++11 concurrency STD ::atomic

 

Summary of this article:

Member types and member functions.

STD :: Thread constructor.

3. Asynchronous.

4. Multithreading passes parameters.

5, Join, detach

6. Obtain the number of CPU cores.

CPP atomic variables and thread safety.

Lambda and multithreading.

9. Time waiting related issues.

10. Thread function expansion.

Multithreaded variable parameters.

12. Thread switching.

13. Thread movement.

 

STD :: Thread is declared in the #include<thread> header, so using STD ::thread requires the #include<thread> header.

 

Member types and member functions.

Member type:

id

Thread id (public member type )                                       id

native_handle_type

Native handle type (public member type )

Member functions:

(constructor)

Construct Thread (public Member Function) constructor

(destructor)

Thread destructor (public member function) destructor

operator=

Move-assign thread (public Member Function) Assignment overload

get_id

Get Thread ID (public member Function) Obtains the thread ID

joinable

Check if Joinable (public Member Function) Checks whether the thread can join the wait

join

Join Thread (public member function) Joins the wait

detach

Detach Thread (public Member Function) Detach thread

swap

Swap Threads (public Member Function) Swap threads

native_handle

Get Native Handle (public member Function) Obtains the thread handle

hardware_concurrency [static]

Detect Hardware concurrency (public static member Function) Detects the hardware concurrency feature

Non – member overloads:

swap (thread)

Swap threads (function )

 

STD :: Thread constructor.

The following table:

default (1)

thread() noexcept;

initialization(2)

template <class Fn, class… Args>   explicit thread (Fn&& fn, Args&&… args);

copy [deleted] (3)

thread (const thread&) = delete;

move [4]

hread (thread&& x) noexcept;

(1). The default constructor creates an empty thread execution object.

(2). Initialize the constructor to create a Thread object that can be joinable. The new thread will call the FN function whose arguments are given by args.

(3). The copy constructor is disabled, meaning that thread cannot be copied.

(4).move constructor, move constructor, after the successful call x does not represent any thread execution object.

Note: Joinable Thread objects must be joined by the main thread or set to detached before they are destroyed.

 

Examples of the various STD ::thread constructors are as follows:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. #include<chrono>  
  4. using namespace std;  
  5. Void fun1(int n) // Initialize the constructor
  6. {  
  7.     cout << “Thread ” << n << ” executing\n”;  
  8.     n += 10;  
  9.     this_thread::sleep_for(chrono::milliseconds(10));  
  10. }  
  11. Void fun2(int &n) // Copy constructor
  12. {  
  13.     cout << “Thread ” << n << ” executing\n”;  
  14.     n += 20;  
  15.     this_thread::sleep_for(chrono::milliseconds(10));  
  16. }  
  17. int main()  
  18. {  
  19.     int n = 0;  
  20. thread t1; // T1 is not a thread
  21. thread t2(fun1, n + 1); // Pass by value
  22.     t2.join();  
  23.     cout << “n=” << n << ‘\n’;  
  24.     n = 10;  
  25. thread t3(fun2, ref(n)); / / reference
  26. thread t4(move(t3)); //t4 executes t3, t3 is not thread
  27.     t4.join();  
  28.     cout << “n=” << n << ‘\n’;  
  29.     return 0;  
  30. }  
  31. Running results:
  32. Thread 1 executing  
  33. n=0  
  34. Thread 10 executing  
  35. n=30</span>  

 

3. Asynchronous.

Such as:

[cpp] view plain copy

  1. <span style=”font-size:12px;” >#include<iostream>

  2. #include<thread>  

  3. using namespace std;  

  4. void show()  

  5. {  

  6.     cout << “hello cplusplus!” << endl;  

  7. }  

  8. int main()  

  9. {  

  10. / / on the stack

  11. thread t1(show); // Initialize execution according to the function

  12.     thread t2(show);  

  13.     thread t3(show);  

  14. // Array of threads

  15.     thread th[3]{

    thread(show), thread(show), thread(show)};   

  16. / / the heap

  17.     thread *pt1(new thread(show));  

  18.     thread *pt2(new thread(show));  

  19.     thread *pt3(new thread(show));  

  20. // Thread pointer array

  21.     thread *pth(new thread[3]{

    thread(show), thread(show), thread(show)});  

  22.     return 0;  

  23. }</span>  

 

4. Multithreading passes parameters.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. void show(const char *str, const int id)  
  5. {  
  6. Cout << “thread” << id + 1 << “:” << STR << endl;
  7. }  
  8. int main()  
  9. {  
  10. thread t1(show, “hello cplusplus!” , 0);
  11. Thread t2(show, “hello C++! , 1);
  12. thread t3(show, “hello!” , 2);
  13.     return 0;  
  14. }  
  15. Running results:
  16. Thread 1 thread 2: hello C++! Thread 3: Hello!
  17. : hello cplusplus!

Threads T1, T2, t3 all executed successfully!

 

5, Join, detach

Join example is as follows:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. #include<array>  
  4. using namespace std;  
  5. void show()  
  6. {  
  7.     cout << “hello cplusplus!” << endl;  
  8. }  
  9. int main()  
  10. {  
  11.     array<thread, 3>  threads = { thread(show), thread(show), thread(show) };  
  12.     for (int i = 0; i < 3; i++)  
  13.     {  
  14. cout << threads[i].joinable() << endl; // Check whether the thread can join
  15. threads[i].join(); // The main thread waits for the current thread to finish executing before exiting
  16.     }  
  17.     return 0;  
  18. }  
  19. Running results:
  20. hello cplusplus!  
  21. hello cplusplus!  
  22. 1  
  23. hello cplusplus!  
  24. 1  
  25. 1</span>  

Conclusion:

Join causes the main thread to wait for all child threads to finish before exiting.

The detach example is as follows:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. void show()  
  5. {  
  6.     cout << “hello cplusplus!” << endl;  
  7. }  
  8. int main()  
  9. {  
  10.     thread th(show);  
  11.     //th.join();   
  12. th.detach(); // If the thread is disconnected from the main thread, the child thread does not report an error, and the child thread automatically exits after executing.
  13. // After detach, the child thread becomes an orphan thread and cannot communicate with each other.
  14.     cout << th.joinable() << endl;  
  15.     return 0;  
  16. }  
  17. Running results:
  18. hello cplusplus!  
  19. 0</span>  

Conclusion:

The thread detach from the main thread, the main thread hangs, the child thread does not report an error, the child thread automatically exits after executing.

After a thread detach, child threads become orphan threads and cannot communicate with each other.

 

6. Obtain the number of CPU cores.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6. auto n = thread::hardware_concurrency(); // Get the number of CPU cores
  7.     cout << n << endl;  
  8.     return 0;  
  9. }  
  10. Running results:
  11. 8</span>  

Conclusion:

Get the number of CPU cores for thread::hardware_concurrency().

 

CPP atomic variables and thread safety.

Questions such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. const int N = 100000000;  
  5. int num = 0;  
  6. void run()  
  7. {  
  8.     for (int i = 0; i < N; i++)  
  9.     {  
  10.         num++;  
  11.     }  
  12. }  
  13. int main()  
  14. {  
  15.     clock_t start = clock();  
  16.     thread t1(run);  
  17.     thread t2(run);  
  18.     t1.join();  
  19.     t2.join();  
  20.     clock_t end = clock();  
  21. Cout < < “num =” < < < < num, “unavailable” < < end – start < < “ms” < < endl;
  22.     return 0;  
  23. }  
  24. Running results:
  25. < span style = “box-sizing: border-box! Important;

The result from the above code execution is not the 200000000 we expected, it is due to a conflict between threads, resulting in incorrect results.

To solve this problem, there are the following methods:

(1) Mutex.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. #include<mutex>  
  4. using namespace std;  
  5. const int N = 100000000;  
  6. int num(0);  
  7. mutex m;  
  8. void run()  
  9. {  
  10.     for (int i = 0; i < N; i++)  
  11.     {  
  12.         m.lock();  
  13.         num++;  
  14.         m.unlock();  
  15.     }  
  16. }  
  17. int main()  
  18. {  
  19.     clock_t start = clock();  
  20.     thread t1(run);  
  21.     thread t2(run);  
  22.     t1.join();  
  23.     t2.join();  
  24.     clock_t end = clock();  
  25. Cout < < “num =” < < < < num, “unavailable” < < end – start < < “ms” < < endl;
  26.     return 0;  
  27. }  
  28. Running results:
  29. Num =200000000, time

It is not hard to see that the calculation results are correct after passing the mutex, but the calculation speed is slow, mainly due to the time required to unlock the mutex.

For details on mutex, see STD ::mutex in C++11 concurrency.

(2) Atomic variables.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. #include<atomic>  
  4. using namespace std;  
  5. const int N = 100000000;  
  6. atomic_int num{ 0 }; // There is no thread conflict
  7. void run()  
  8. {  
  9.     for (int i = 0; i < N; i++)  
  10.     {  
  11.         num++;  
  12.     }  
  13. }  
  14. int main()  
  15. {  
  16.     clock_t start = clock();  
  17.     thread t1(run);  
  18.     thread t2(run);  
  19.     t1.join();  
  20.     t2.join();  
  21.     clock_t end = clock();  
  22. Cout < < “num =” < < < < num, “unavailable” < < end – start < < “ms” < < endl;
  23.     return 0;  
  24. }  
  25. Running results:
  26. Num =200000000, ms

It is not difficult to find that the calculation results are correct and the calculation speed is average after passing atomic variables.

Refer to STD ::atomic in C++11 for details on atomic variables.

(3) Join join.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. const int N = 100000000;  
  5. int num = 0;  
  6. void run()  
  7. {  
  8.     for (int i = 0; i < N; i++)  
  9.     {  
  10.         num++;  
  11.     }  
  12. }  
  13. int main()  
  14. {  
  15.     clock_t start = clock();  
  16.     thread t1(run);  
  17.     t1.join();  
  18.     thread t2(run);  
  19.     t2.join();  
  20.     clock_t end = clock();  
  21. Cout < < “num =” < < < < num, “unavailable” < < end – start < < “ms” < < endl;
  22.     return 0;  
  23. }  
  24. Running results:
  25. Num =200000000, span

It is not difficult to find that the calculation results are correct and the calculation speed is ideal after passing through atomic variables.

 

Lambda and multithreading.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     auto fun = [](const char *str) {cout << str << endl; };  
  7. thread t1(fun, “hello world!” );
  8. thread t2(fun, “hello beijing!” );
  9.     return 0;  
  10. }  
  11. Running results:
  12. hello world!  
  13. hello beijing!

 

9. Time waiting related issues.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. #include<chrono>  
  4. using namespace std;  
  5. int main()  
  6. {  
  7.     thread th1([]()  
  8.     {  
  9. // Make the thread wait 3 seconds
  10.         this_thread::sleep_for(chrono::seconds(3));  
  11. // Let the CPU execute other idle threads
  12.         this_thread::yield();  
  13. / / thread id
  14.         cout << this_thread::get_id() << endl;  
  15.     });  
  16.     return 0;  
  17. }</span>  

 

10. Thread function expansion.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. Class MyThread :public thread // Inherit thread
  5. {  
  6. public:  
  7. // Subclass MyThread() extends the constructor of thread()
  8.     MyThread() : thread()  
  9.     {  
  10.     }  
  11. //MyThread() initializes the constructor
  12. template
  13. MyThread(T&&func, Args&&… args) : thread(forward

    (func), forward

    (args)…)

  14.     {  
  15.     }  
  16. Void showcmd(const char * STR) // Run system
  17.     {  
  18.         system(str);  
  19.     }  
  20. };  
  21. int main()  
  22. {  
  23.     MyThread th1([]()  
  24.     {  
  25.         cout << “hello” << endl;  
  26.     });  
  27. th1.showcmd(“calc”); / / run calc
  28.     //lambda  
  29.     MyThread th2([](const char * str)  
  30.     {  
  31.         cout << “hello” << str << endl;  
  32.     }, ” this is MyThread”);  
  33. th2.showcmd(“notepad”); / / run notepad
  34.     return 0;  
  35. }  
  36. Running results:
  37. hello  
  38. / / run calc
  39. hello this is MyThread  
  40. / / run notepad < / span >

 

Multithreaded variable parameters.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. #include<cstdarg>  
  4. using namespace std;  
  5. int show(const char *fun, …)  
  6. {  
  7. va_list ap; / / pointer
  8. va_start(ap, fun); / /
  9. vprintf(fun, ap); / / call
  10.     va_end(ap);  
  11.     return 0;  
  12. }  
  13. int main()  
  14. {  
  15. thread t1(show, “%s %d %c %f”, “hello world!” , 100, ‘A’, 3.14159);
  16.     return 0;  
  17. }  
  18. Running results:
  19. hello world! 100 A 3.14159 < / span >

 

12. Thread switching.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     thread t1([]()  
  7.     {  
  8.         cout << “thread1” << endl;  
  9.     });  
  10.     thread t2([]()  
  11.     {  
  12.         cout << “thread2” << endl;  
  13.     });  
  14.     cout << “thread1′ id is ” << t1.get_id() << endl;  
  15.     cout << “thread2′ id is ” << t2.get_id() << endl;  
  16.       
  17.     cout << “swap after:” << endl;  
  18. swap(t1, t2); // Thread swap
  19.     cout << “thread1′ id is ” << t1.get_id() << endl;  
  20.     cout << “thread2′ id is ” << t2.get_id() << endl;  
  21.     return 0;  
  22. }  
  23. Running results:
  24. thread1  
  25. thread2  
  26. thread1′ id is 4836  
  27. thread2′ id is 4724  
  28. swap after:  
  29. thread1′ id is 4724  
  30. thread2′ id is 4836</span>  

Two threads swap via swap.

 

13. Thread movement.

Such as:

[cpp] view plain copy

  1. #include
  2. #include<thread>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     thread t1([]()  
  7.     {  
  8.         cout << “thread1” << endl;  
  9.     });  
  10.     cout << “thread1′ id is ” << t1.get_id() << endl;  
  11.     thread t2 = move(t1);;  
  12.     cout << “thread2′ id is ” << t2.get_id() << endl;  
  13.     return 0;  
  14. }  
  15. Running results:
  16. thread1  
  17. thread1′ id is 5620  
  18. thread2′ id is 5620</span>  

From the above code, thread T2 can move T1 to get all the attributes of T1, while T1 is destroyed.

 

 

C++ threads are also useful. They can also be started like qt threads, and the run function is the actual running code for the thread. “Thread” and “this_thread” methods are rare, but there are only a few commonly used.

 

1. STD ::this_thread::get_id Retrieves the thread ID

2. Yield, and sleep. Yield, the yield of CPU ownership, can be used in multithreaded loops to reduce CPU idle

3. Detach the thread from qt by default. The actual code of join is usually not used, but is used when the main thread waits for other threads to finish.

 

[cpp] view plain copy

  1. #include <thread>  
  2.   
  3. class TestThread  
  4. {  
  5. public:  
  6.     void start(){   
  7.         thread t(std::bind(&TestThread::run,this));  
  8.         t.detach();  
  9.     }  
  10.   
  11.   
  12.     void run(){  
  13.         while (true){  
  14.             cout << “test thread id:” << std::this_thread::get_id()<<endl;  
  15.             std::this_thread::sleep_for(std::chrono::milliseconds(2000));  
  16.         }  
  17.     }  
  18. };  
  19.   
  20.   
  21. void run(){  
  22.     while (true){  
  23.         cout << “function thread id:” << std::this_thread::get_id() << endl;  
  24.         std::this_thread::sleep_for(std::chrono::milliseconds(2000));  
  25.     }  
  26. }  
  27.   
  28.   
  29. int main(void)  
  30. {  
  31.     cout << “main thread id:” << std::this_thread::get_id() << endl;  

[cpp] view plain copy

  1. TestThread testThread;  
  2. testThread.start();  

[cpp] view plain copy

  1.     thread funcThread(&run);  
  2.     funcThread.detach();  
  3.   
  4.     getchar();  
  5.     return 0;  
  6. }