case1: create thread 1 join, detach
Create a thread and wait for it to finish executing and print the id of both threads
#include <iostream> #include <thread> using namespace std; void func() { cout << "hello , this is my thread, thread id is " << this_thread::get_id() << endl; } int main() { thread th = thread(func); th.join(); cout << "this is main thread and its id is " << this_thread::get_id() << endl; }
The results are as follows:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe hello , this is my thread, thread id is 2 this is main thread and its id is 1 Process finished with exit code 0
Using detach, discard control of the thread:
#include <iostream> #include <thread> using namespace std; void func() { cout << "hello , this is my thread, thread id is " << this_thread::get_id() << endl; } int main() { thread th = thread(func); th.detach(); // detach can be used if we are no longer concerned with the running of this thread at this time cout << th.joinable() << endl; cout << "this is main thread and its id is " << this_thread::get_id() << endl; }
Run result:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe 0 this is main thread and its id is 1 hello , this is my thread, thread id is 2 Process finished with exit code 0
case2: Create thread 2 threads to pass values or references
Pass Value
#include <iostream> #include <thread> using namespace std; void func(string s) { cout << "hello , this is my thread, thread arg is " << s << endl; } int main() { thread th = thread(func, "test"); th.join(); cout << "this is main thread and its id is " << this_thread::get_id() << endl; }
The printout is as follows:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe hello , this is my thread, thread arg is test this is main thread and its id is 1 Process finished with exit code 0
Pass-by reference
#include <iostream> #include <thread> using namespace std; void func(string& s) { cout << (&s) << endl; cout << "hello , this is my thread, thread arg is " << s << endl; } int main() { string str = "test"; thread th = thread(func, ref(str)); cout << (&str) << endl; th.join(); cout << "this is main thread and its id is " << this_thread::get_id() << endl; }
The printout is as follows:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe 0x62fd10 0x62fd10 hello , this is my thread, thread arg is test this is main thread and its id is 1 Process finished with exit code 0
case3: Create a thread to pass a functional object as a parameter
As to the definition of the analog function, you can see: functor
If you simply pass a logical function into a thread, it is not good when the logic of the function is more complex.
Encapsulating a function inside a class gives it some encapsulation and creates a data structure inside the class, such as a map, to record the state of the function.
Function-like, parameterized
#include <iostream> #include <thread> using namespace std; // functional object struct A { void operator()() { cout << "I'm A" << endl; } }; void show() { cout << "I'm show" << endl; } int main() { show(); A a; a(); // Equivalent to a.operator(); // We call this object callable, also known as a function-like thread thread1 = thread(A()); thread1.join(); return 0; }
The printout is as follows:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe I'm show I'm A I'm A Process finished with exit code 0
Parameterized function
#include <iostream> #include <thread> using namespace std; // functional object struct A { void operator()(int num) { for (int i = 0; i < num; i++) { cout << "I'm A" << i << endl; } } }; int main() { int num = 10; thread thread1 = thread(A(), num); for (int i = 0; i < num; i++) { cout << "I'm main" << i << endl; } thread1.join(); return 0; }
The printout is out of order and multithreaded as follows
And cout s aren't thread safe, so you can see that they look messy
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe I'm mainI'm A00 I'm A1 I'm A2 I'm A3 I'm AI'm main41 I'm mainI'm A25 I'm mainI'm A36 I'm AI'm main47 I'm main5 I'm mainI'm A86 I'm mainI'm A97 I'm main8 I'm main9 Process finished with exit code 0
lambda function as parameter
#include <iostream> #include <thread> using namespace std; int main() { string s = "test"; thread f = thread([&s](int a,int b) { cout << s << endl; cout << a + b << endl; }, 2, 3); f.join(); return 0; }
Print results:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe test 5 Process finished with exit code 0
case4: Watch for multithreaded programs to speed up calculations
#include <iostream> #include <thread> using namespace std; // Measure the running time of a function template <class T> void measure(T&& func) { using namespace std::chrono; auto start = system_clock::now(); // func func(); duration<double> diff = system_clock::now() - start; cout << "Executed" << diff.count() << "second" << endl; } // Sum function [start,end) void sum(long start, long end, long& ans) { long s = 0; for(auto i = start; i < end; i++) { s += i; } ans = s; } const long S = 100000000; int main() { // Measure how long the work is allocated to two threads measure([](){ long ans1, ans2; thread t1 = thread(sum, 0, S >> 1, std::ref(ans1)); thread t2 = thread(sum, S >> 1, S, std::ref(ans2)); t1.join(); t2.join(); cout << "ans = " << ans1 + ans2 << endl; }); // Measure single-threaded working hours measure([](){ long ans; sum(0, S, ans); cout << "ans = " << ans << endl; }); return 0; }
Print results:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe ans = 887459712 Executed 0.13546 second ans = 887459712 Executed 0.240006 second Process finished with exit code 0
Of course, here's one detail:
If we pass in a ref reference in a multi-threaded program, it is better not to operate directly on this ref value in a threaded program, but to use a temporary variable, such as s in the program above, which is added up and then assigned to ans. This will improve the efficiency of the program.
case5:future + get to get concurrent results
The future package thread runs as follows:
Since the result of our thread function is long, define future <long>
#include <iostream> #include <thread> #include <future> #include <vector> using namespace std; // Measure the running time of a function template <class T> void measure(T&& func) { using namespace std::chrono; auto start = system_clock::now(); // func func(); duration<double> diff = system_clock::now() - start; cout << "Executed" << diff.count() << "second" << endl; } // Sum function [start,end) long sum(long start, long end) { long s = 0; for(auto i = start; i < end; i++) { s += i; } return s; } const long S = 100000000; int main() { // Measure how long it takes to allocate work to threadNums threads measure([](){ const long threadNums = 8; vector<future<long>> vec; vec.reserve(threadNums); for (int i = 0; i < threadNums; i++) { vec.push_back(async(sum, (S / threadNums) * i, (S / threadNums) * (i + 1))); } long ans = 0; // get blocked concurrent results for (int i = 0; i < threadNums; i++) { ans += vec[i].get(); } cout << "ans = " << ans << endl; }); // Measure single-threaded working hours measure([](){ long ans = sum(0, S); cout << "ans = " << ans << endl; }); return 0; }
The results are as follows:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe ans = 887459712 Executed 0.0521455 second ans = 887459712 Executed 0.250044 second Process finished with exit code 0
case6: mutex
Multiple threads access the same value and modify it, resulting in data competition.
#include <iostream> #include <thread> #include <future> #include <vector> using namespace std; // Measure the running time of a function template <class T> void measure(T&& func) { using namespace std::chrono; auto start = system_clock::now(); // func func(); duration<double> diff = system_clock::now() - start; cout << "Executed" << diff.count() << "second" << endl; } std::mutex mtx; // Thread-safe summation function void sum(long& s) { mtx.lock(); for (int i = 0; i < 100000; i++) { s++; } mtx.unlock(); } int main() { // Measure how long it takes to allocate work to threadNums threads measure([](){ vector<thread> v; long s = 0; for (int i = 0; i < 4; i++) { v.emplace_back(std::thread(sum, std::ref(s))); } for (int i = 0; i < 4; i++) { v[i].join(); } cout << "ans " << s << endl; }); measure([](){ long s = 0; for (int i = 0; i < 4; i++) { sum(s); } cout << "ans " << s << endl; }); return 0; }
Test results:
C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe ans 400000 Executed 0.0141654 second ans 400000 Executed 0.0155926 second Process finished with exit code 0
Note reference:
C++ Multithreaded Quick Start