C ++ 11 [рднрд╛рдЧ 2] рдореЗрдВ рдзрд╛рд░рд╛рдПрдБ, рддрд╛рд▓реЗ рдФрд░ рд╕рд╢рд░реНрдд рдЪрд░

рдЗрд╕ рд▓реЗрдЦ рдХреА рдЕрдзрд┐рдХ рд╕рдВрдкреВрд░реНрдг рд╕рдордЭ рдХреЗ рд▓рд┐рдП, рдЗрд╕рдХреЗ рдкрд╣рд▓реЗ рднрд╛рдЧ рдХреЛ рдкрдврд╝рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЧрдИ рд╣реИ, рдЬрд╣рд╛рдВ рдереНрд░реЗрдбреНрд╕ рдФрд░ рд▓реЙрдХреНрд╕ рдкрд░ рдореБрдЦреНрдп рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдпрд╣ рдХрдИ рдмрд┐рдВрджреБрдУрдВ (рд╢рд░реНрддреЛрдВ, рдХрд╛рд░реНрдпреЛрдВ рдЖрджрд┐) рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣рд╛рдВ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рдмрд┐рдирд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдпрд╣ рд▓реЗрдЦ рд╕рд╢рд░реНрдд рдЪрд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдЧрд╛ ...

рд╕рд╢рд░реНрдд рдЪрд░


рдкрд╣рд▓реЗ рд╡рд░реНрдгрд┐рдд рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, C ++ 11 рд╕рд╢рд░реНрдд рдЪрд░ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдпрд╛ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдереНрд░реЗрдбреНрд╕ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рдереНрд░реЗрдб рд╕реЗ рдХреЛрдИ рд╕реВрдЪрдирд╛ рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ рдпрд╛ рдПрдХ рдкреМрд░рд╛рдгрд┐рдХ рд╕реНрдкрд░реВрдк ("рдЧрд▓рдд / рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╡реЗрдХрдЕрдк") рд╣реЛрддрд╛ рд╣реИред
<condition_variable> рд╢реАрд░реНрд╖ рд▓реЗрдЦ рдореЗрдВ рд╕рд╢рд░реНрдд рдЪрд░ рдХреЗ рджреЛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЙрдкрд▓рдмреНрдз рд╣реИрдВ:

рдореИрдВ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ рдХрд┐ рд╕рд╢рд░реНрдд рдЪрд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ:

рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рдзрд╛рдЧреЗ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╢рд░реНрдд рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рддрд╛ рд╣реИ: рдХреБрдЫ рдереНрд░реЗрдбреНрд╕ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рджреМрд░рд╛рди (рдЪрд▓реЛ рдЙрдиреНрд╣реЗрдВ "рд╢реНрд░рдорд┐рдХ" рдХрд╣рддреЗ рд╣реИрдВ) рдПрдХ рддреНрд░реБрдЯрд┐ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдЬрдмрдХрд┐ рдЙрдиреНрд╣реЗрдВ рдХрддрд╛рд░ рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред "рд░рдЬрд┐рд╕реНрдЯреНрд░рд╛рд░" рдереНрд░реЗрдб рдЗрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ (рдЙрдиреНрд╣реЗрдВ рдХрддрд╛рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛) рдФрд░ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИред рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ "рдкрдВрдЬреАрдпрдХ" рдХреЛ "рд╢реНрд░рдорд┐рдХ" рд╕рдВрдХреЗрдд рджреЗрддрд╛ рд╣реИред рд░рдЬрд┐рд╕реНрдЯреНрд░рд╛рд░ рдПрдХ рд╕рд╢рд░реНрдд рдЪрд░ рд╕рдВрдХреЗрдд рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред рдЭреВрдареА рдЬрд╛рдЧреГрддрд┐ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдореНрдореАрдж рд▓реВрдк рдореЗрдВ рд╣реЛрддреА рд╣реИ рдЬрд╣рд╛рдВ рдмреВрд▓рд┐рдпрди рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХреА рдЬрд╛рддреА рд╣реИред
 #include <condition_variable> #include <iostream> #include <random> #include <thread> #include <mutex> #include <queue> std::mutex g_lockprint; std::mutex g_lockqueue; std::condition_variable g_queuecheck; std::queue<int> g_codes; bool g_done; bool g_notified; void workerFunc(int id, std::mt19937 &generator) { //   { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[worker " << id << "]\trunning..." << std::endl; } //   std::this_thread::sleep_for(std::chrono::seconds(1 + generator() % 5)); //   int errorcode = id*100+1; { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[worker " << id << "]\tan error occurred: " << errorcode << std::endl; } //    { std::unique_lock<std::mutex> locker(g_lockqueue); g_codes.push(errorcode); g_notified = true; g_queuecheck.notify_one(); } } void loggerFunc() { //   { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[logger]\trunning..." << std::endl; } //   ,      while(!g_done) { std::unique_lock<std::mutex> locker(g_lockqueue); while(!g_notified) //    g_queuecheck.wait(locker); //     ,   while(!g_codes.empty()) { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[logger]\tprocessing error: " << g_codes.front() << std::endl; g_codes.pop(); } g_notified = false; } } int main() { //   -  std::mt19937 generator((unsigned int)std::chrono::system_clock::now().time_since_epoch().count()); //   std::thread loggerThread(loggerFunc); //   std::vector<std::thread> threads; for(int i = 0; i < 5; ++i) threads.push_back(std::thread(workerFunc, i+1, std::ref(generator))); for(auto &t: threads) t.join(); //        g_done = true; loggerthread.join(); return 0; } 

рдЗрд╕ рдХреЛрдб рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди рд▓рдЧрднрдЧ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рдгрд╛рдо рджреЗрдЧрд╛ (рдкрд░рд┐рдгрд╛рдо рд╣рд░ рдмрд╛рд░ рдЕрд▓рдЧ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рд╕реВрддреНрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ (рдпрд╛ рдмрд▓реНрдХрд┐ рд╕реЛрддреЗ рд╕рдордп) рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдордп рдЕрдВрддрд░рд╛рд▓):
 [logger] running... [worker 1] running... [worker 2] running... [worker 3] running... [worker 4] running... [worker 5] running... [worker 1] an error occurred: 101 [worker 2] an error occurred: 201 [logger] processing error: 101 [logger] processing error: 201 [worker 5] an error occurred: 501 [logger] processing error: 501 [worker 3] an error occurred: 301 [worker 4] an error occurred: 401 [logger] processing error: 301 [logger] processing error: 401 

рдКрдкрд░ рджреА рдЧрдИ wait рд╡рд┐рдзрд┐ рдореЗрдВ рджреЛ рдЕрдзрд┐рднрд╛рд░ рд╣реИрдВ:

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рджреВрд╕рд░реЗ рдЕрдзрд┐рднрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЖрдк рдКрдкрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдмреВрд▓рд┐рдпрди рдзреНрд╡рдЬ g_notified рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдмрдЪ рд╕рдХрддреЗ рд╣реИрдВ:
 void workerFunc(int id, std::mt19937 &generator) { //   { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[worker " << id << "]\trunning..." << std::endl; } //   std::this_thread::sleep_for(std::chrono::seconds(1 + generator() % 5)); //   int errorcode = id*100+1; { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[worker " << id << "]\tan error occurred: " << errorcode << std::endl; } //    { std::unique_lock<std::mutex> locker(g_lockqueue); g_codes.push(errorcode); g_queuecheck.notify_one(); } } void loggerFunc() { //   { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[logger]\trunning..." << std::endl; } //   ,      while(!g_done) { std::unique_lock<std::mutex> locker(g_lockqueue); g_queuecheck.wait(locker, [&](){return !g_codes.empty();}); //     ,   while(!g_codes.empty()) { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "[logger]\tprocessing error: " << g_codes.front() << std::endl; g_codes.pop(); } } } 

рдЕрддрд┐рднрд╛рд░рд┐рдд wait() рд╡рд┐рдзрд┐ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд┐рдзреЗрдп рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рдЕрдзрд┐рднрд╛рд░ рдХреЗ рд╕рд╛рде рджреЛ рдФрд░ рд╕рдорд╛рди рд╡рд┐рдзрд┐рдпрд╛рдВ рд╣реИрдВ:

рдПрдХ рд╡рд┐рдзреЗрдп рд░рд┐рдЯрд░реНрди рдХреЗ рдмрд┐рдирд╛ рдЗрди рддрд░реАрдХреЛрдВ рдХреЛ рдУрд╡рд░рд▓реЛрдб рдХрд░рдирд╛ cv_status рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рдЯрд╛рдЗрдордЖрдЙрдЯ рд╣реБрдЖ рд╣реИ, рдпрд╛ рд╕рд╢рд░реНрдд рдЪрд░ рд╕рдВрдХреЗрдд рдХреЗ рдХрд╛рд░рдг рд╡реЗрдХрдЕрдк рд╣реБрдЖ рд╣реИ, рдпрд╛ рдпрд╣ рдПрдХ рдЧрд▓рдд рд╡реЗрдХрдЕрдк рд╣реИред

Std рднреА Inform_all_at_thread_exit рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЕрдиреНрдп рдереНрд░реЗрдбреНрд╕ рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрдВрддреНрд░ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рдиреЗ рдЕрдкрдирд╛ рдХрд╛рдо рдкреВрд░рд╛ рдХрд░ рд▓рд┐рдпрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕рднреА thread_local рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХрд╛ рд╡рд┐рдирд╛рд╢ рднреА рд╢рд╛рдорд┐рд▓ рд╣реИред join рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рддрдВрддреНрд░ рджреНрд╡рд╛рд░рд╛ рдереНрд░реЗрдбреНрд╕ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдкрд░ рдЕрд╕рд╛рдорд╛рдиреНрдп рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реЛ thread_locals рд╣реИ рдЬрдм thread_locals рдкрд╣рд▓реЗ рд╣реА рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛ рдЪреБрдХреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ thread_locals рдХреЛ рдереНрд░реЗрдб рдЬрд╛рдЧрдиреЗ рдХреЗ рдмрд╛рдж рдпрд╛ рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╣реА рдкреВрд░рд╛ рд╣реЛ рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рджреЗрдЦреЗрдВ N3070 рдФрд░ N2880 ред рдЖрдорддреМрд░ рдкрд░, рдПрдХ рдХреЙрд▓) рдпрд╣ рдХрд╛рд░реНрдп рдереНрд░реЗрдб рдХреЗ рдЕрд╕реНрддрд┐рддреНрд╡ рдореЗрдВ рдЖрдиреЗ рд╕реЗ рдареАрдХ рдкрд╣рд▓реЗ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдХрд┐ рдХреИрд╕реЗ рджреЛ рдзрд╛рдЧреЗ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╢рд░реНрдд рдЪрд░ рдХреЗ рд╕рд╛рде notify_all_at_thread_exit рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
 std::mutex g_lockprint; std::mutex g_lock; std::condition_variable g_signal; bool g_done; void workerFunc(std::mt19937 &generator) { { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "worker running..." << std::endl; } std::this_thread::sleep_for(std::chrono::seconds(1 + generator() % 5)); { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "worker finished..." << std::endl; } std::unique_lock<std::mutex> lock(g_lock); g_done = true; std::notify_all_at_thread_exit(g_signal, std::move(lock)); } int main() { std::mt19937 generator((unsigned int)std::chrono::system_clock::now().time_since_epoch().count()); std::cout << "main running..." << std::endl; std::thread worker(workerFunc, std::ref(generator)); worker.detach(); std::cout << "main crunching..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1 + generator() % 5)); { std::unique_lock<std::mutex> locker(g_lockprint); std::cout << "main waiting for worker..." << std::endl; } std::unique_lock<std::mutex> lock(g_lock); while(!g_done) //    g_signal.wait(lock); std::cout << "main finished..." << std::endl; return 0; } 

рдпрджрд┐ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдореБрдЦреНрдп рд╕реВрддреНрд░ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдкрдирд╛ рдХрд╛рдо рдкреВрд░рд╛ рдХрд░ рд▓реЗрддрд╛ рд╣реИ, рддреЛ рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:
 main running... worker running... main crunching... worker finished... main waiting for worker... main finished... 

рдпрджрд┐ рдореБрдЦреНрдп рдзрд╛рдЧрд╛ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдереНрд░реЗрдб рд╕реЗ рдкрд╣рд▓реЗ рдЕрдкрдирд╛ рдХрд╛рдо рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:
 main running... worker running... main crunching... main waiting for worker... worker finished... main finished... 


рдирд┐рд╖реНрдХрд░реНрд╖ рдореЗрдВ


C ++ 11 рдорд╛рдирдХ C ++ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдорд╛рдирдХ, рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╕реНрд╡рддрдВрддреНрд░ рддрд░реАрдХреЗ рд╕реЗ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣ рд▓реЗрдЦ std рд╕реЗ рд╕реНрдЯреНрд░реАрдо рдФрд░ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рддрдВрддреНрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рд░рди рд╣реИред <thread> рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ <thread> рд╣реЗрдбрд░ рдПрдХ рд╣реА рдирд╛рдо (рдФрд░ рдХрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝рдВрдХреНрд╢рди) рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд░реНрдЧ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред <mutex> рд╣реЗрдбрд░ рдереНрд░реЗрдбреНрд╕ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдореНрдпреВрдЯреЗрдХреНрд╕ рдФрд░ "рд░реИрдкрд░" рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред <condition_variable> рд╢реАрд░реНрд╖ рд▓реЗрдЦ рд╕рд╢рд░реНрдд рдЪрд░ рдХреЗ рджреЛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдПрдХ рдпрд╛ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдереНрд░реЗрдбреНрд╕ рдмреНрд▓реЙрдХ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЬрдм рддрдХ рдХрд┐ рдЖрдк рдХрд┐рд╕реА рдЕрдиреНрдп рдзрд╛рдЧреЗ рд╕реЗ рдпрд╛ рдЭреВрдареА рдЬрд╛рдЧреГрддрд┐ рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рдкреНрд░рд╛рдкреНрдд рди рдХрд░реЗрдВред рдорд╛рдорд▓реЗ рдХреА рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдЬрд╛рдирдХрд╛рд░реА рдФрд░ рд╕рдордЭ рдХреЗ рд▓рд┐рдП, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рд╛рд╣рд┐рддреНрдп рдкрдврд╝рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЧрдИ рд╣реИ :)

Source: https://habr.com/ru/post/In182626/


All Articles