std::async介绍 下面是一个很好的并行计算的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <future> #include <iostream> #include <string> bool is_prime (int x) { for (int i = 2 ; i < x; i++) { if (x % i == 0 ) return false ; } return true ; } int main () { std::future<bool > fut = std::async (is_prime, 700020007 ); std::cout << "please wait" ; std::chrono::milliseconds span (100 ) ; while (fut.wait_for (span) != std::future_status::ready) std::cout << "." ; std::cout << std::endl; std::cout << "final result: " << std::boolalpha << fut.get () << std::endl; system ("pause" ); return 0 ; }
std::async中的第一个参数是启动策略,它控制std::async的异步行为,我们可以用三种不同的启动策略来创建std::async·std::launch::async 保证异步行为,即传递函数将在单独的线程中执行·std::launch::deferred 当其他线程调用get()来访问共享状态时,将调用非异步行为·std::launch::async | std::launch::deferred 默认行为。有了这个启动策略,它可以异步运行或不运行,这取决于系统的负载,但我们无法控制它。
见下面例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #include <iostream> #include <string> #include <chrono> #include <thread> #include <future> using namespace std::chrono;std::string fetchDataFromDB (std::string recvData) { std::this_thread::sleep_for (seconds (5 )); return "DB_" + recvData; } std::string fetchDataFromFile (std::string recvData) { std::this_thread::sleep_for (seconds (5 )); return "File_" + recvData; } int main () { system_clock::time_point start = system_clock::now (); std::future<std::string> resultFromDB = std::async (std::launch::async, fetchDataFromDB, "Data" ); std::string fileData = fetchDataFromFile ("Data" ); std::string dbData = resultFromDB.get (); auto end = system_clock::now (); auto diff = duration_cast <std::chrono::seconds>(end - start).count (); std::cout << "Total Time taken= " << diff << "Seconds" << std::endl; std::string data = dbData + " :: " + fileData; std::cout << "Data = " << data << std::endl; return 0 ; }
std::promise介绍 std::promise的作用就是提供一个不同线程之间的数据同步机制,它可以存储一个某种类型的值,并将其传递给对应的future, 即使这个future不在同一个线程中也可以安全的访问到这个值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <functional> #include <thread> #include <future> void print_int (std::future<int >& fut) { std::cout << "Enter print_int: " << std::endl; int x = fut.get (); std::cout << "value: " << x << '\n' ; } int main () { std::promise<int > prom; std::future<int > fut = prom.get_future (); std::thread th1 (print_int, std::ref(fut)) ; std::this_thread::sleep_for (std::chrono::seconds (3 )); prom.set_value (10 ); th1. join (); system ("pause" ); return 0 ; }
std::packaged_task介绍 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <iostream> #include <future> #include <chrono> #include <thread> int countdown (int from, int to) { for (int i = from; i != to; --i) { std::cout << i << '\n' ; std::this_thread::sleep_for (std::chrono::seconds (1 )); } std::cout << "Lift off!\n" ; return from - to; } int main () { std::packaged_task<int (int , int ) > tsk (countdown) ; std::future<int > ret = tsk.get_future (); std::thread th (std::move(tsk), 10 , 0 ) ; th.detach (); int value = ret.get (); std::cout << "The countdown lasted for " << value << " seconds.\n" ; system ("pause" ); return 0 ; }
硬件支持的线程数量 由于硬件支持的并行线程数量有限,如果创建线程的数量比硬件支持的数量要多,那么CPU进行的上下文切换可能会浪费大量时间,所以了解硬件支持的线程数量是高效并行编程的重点。
使用std::thread::hardware_concurrency()
来获取硬件支持的线程数量。
1 2 3 4 5 6 7 #include <iostream> #include <thread> int main () { unsigned int n = std::thread::hardware_concurrency (); std::cout << n << " concurrent threads are supported.\n" ; }
std::thread::yield介绍 关于std::thread::yield 和 std::sleep_for的比较
例子:
1 2 3 4 5 6 7 8 9 10 11 12 void worker_thread () { while (true ) { std::function<void ()> task; if (work_queue.try_pop (task)) { task (); } else { std::this_thread::yield (); } } }