1. Continuation of atomic operation std::atomic
-
General atomic operations are supported for + +, -, + =, & =, | =, ^ =, and others may not be supported.
-
Example code:
#include <iostream> #include <thread> #include <future> using namespace std; //We encapsulate an object (value) of type int, which has the nature of atomic operation. We can operate the G as if we operated on a variable of type int_ mycount std::atomic<int> g_mycount = 0; void mythread() //Thread entry function { for (int i = 0; i < 1000000; i++) { //g_mycount++; // The atomic operation of the corresponding operation room will not be interrupted //g_mycount += 1; // Results and G_ Same as MYCOUNT + + g_mycount = g_mycount + 1; //The result is wrong } return; } int main() { thread mytobj1(mythread); thread mytobj2(mythread); mytobj1.join(); mytobj2.join(); cout << "Two threads are executed, and finally g_mycount The results are:" << g_mycount << endl; cout << "I love China!" << endl; return 0; }
The results are as follows:
The result is incorrect, indicating that the sdt::atomic atomic operation does not support g_mycount = g_mycount + 1.
2. std::async in depth
2.1 std::async is used to create an asynchronous task
std::future<int> result = std::async(mythread);
std::lanuch::deferred
std::future<int> result = std::async(std::launch::deferred, mythread);
- The first parameter position of std::async() is used to delay the call and do not create a new thread. The execution of mythread() is delayed until the future object calls get() or wait(). If get() or wait() is not called, mythread() will not be executed.
std::lanuch::async
std::future<int> result = std::async(std::launch::async, mythread);
- The first parameter of std::async() is used to force the asynchronous task to execute on a new thread, which means that the system must create a new thread for me to execute mythread().
launch::async | launch::deferred
std::future<int> result = std::async(std::launch::deferred | std::launch::async, mythread);
-
Automatic: The function chooses the policy automatically (at some point). This depends on the system and library implementation, which generally optimizes for the current availability of concurrency in the system.
-
Auto: this function selects the policy automatically (at a certain point). This depends on the system and library implementation and is usually optimized for the current availability of concurrency in the system.
-
This means that the behavior of calling async may be "create a new thread and execute it immediately" or "do not create a new thread and delay the execution of the task entry function until the call to get(), either.
Without additional parameters, only an entry name function is given to async function
std::future<int> result = std::async(std::launch::deferred | std::launch::async, mythread);
-
The default value is launch::async | launch::deferred.
-
The system will decide whether to run asynchronously (create a new thread) or synchronously (do not create a new thread).
2.2 differences between STD:: async and std::thread
- std::thread(): if system resources are tight, std::thread() may fail to create a thread, and the whole program may crash when executing std::thread().
- std::async() is generally not called creating a thread (even if async can create a thread), we usually call it creating an asynchronous task.
- The most obvious difference between std::async() and std::thread() is that std::async() sometimes does not create new threads.
- std::thread() is the way to create a thread. If there is a thread return value, it is not easy to get this value.
- std::async() creates an asynchronous task, which may or may not create a thread, but it is easy to get the return value of the thread entry function when std::async() calls the method.
- Due to system resource constraints:
- If too many threads are created with std::thread, the creation may fail, the system reports an exception and crashes.
- If you use std::async, you will generally not report an exception or crash, because when system resources are tight and it is impossible to create a new thread, the call of std::async without additional parameters will not create a new thread. Instead, the subsequent person who calls get() to request the result will run on the thread where the get() statement is executed.
- If you force std::async to create a new thread, you must use std::lanuch::async. The cost is that the program crashes when the system resources are tight.
- Experience: the number of threads in a program should not exceed 100-200.
2.3 solution of STD:: async uncertainty problem
- Use the std::future::wait_for() function to judge the status
Example code:
#include <iostream> #include <thread> #include <future> using namespace std; int mythread() { cout << "mythread() start " << " threadid = " << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(5000); //5s std::this_thread::sleep_for(dura); return 1; } int main() { cout << "main start " << " threadid = " << std::this_thread::get_id() << endl; std::future<int> result = std::async(mythread); std::future_status status = result.wait_for(0s); //0s: zero seconds is equivalent to std::chrono::microseconds(0) if (status == std::future_status::deferred) { //The task is delayed (due to the shortage of system resources, the std::lanuch::deferred strategy is adopted) cout << result.get() << endl; } else { //The task has not been postponed, it has started running, and the thread has been created if (status == std::future_status::ready) { cout << "Thread successfully executed and returned!" << endl; cout << result.get() << endl; } else if (status == std::future_status::timeout) { cout << "Timeout. The thread has not finished executing. Wait a minute" << endl; cout << result.get() << endl; } } return 0; }
Note: I study c + + multithreading video address: C + + multithreaded learning address