рдЗрд╕ рд▓реЗрдЦ рдХрд╛ рдкрд╣рд▓рд╛ рднрд╛рдЧ C ++ 11 рдореЗрдВ рдереНрд░реЗрдбреНрд╕ рдФрд░ рд▓реЙрдХ рдкрд░ рдХреЗрдВрджреНрд░рд┐рдд рд╣реЛрдЧрд╛, рдЙрдирдХреЗ рд╕рднреА рдорд╣рд┐рдорд╛ рдореЗрдВ рд╕рд╢рд░реНрдд рдЪрд░
рджреВрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛рдПрдЧреА ...
рдзрд╛рд░рд╛рдУрдВ
C ++ 11 рдореЗрдВ, рдереНрд░реЗрдбреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо
std::thread
рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
std::thread
рдХреНрд▓рд╛рд╕ (
<thread>
рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓ рд╕реЗ рд╕реБрд▓рдн), рдЬреЛ рдирд┐рдпрдорд┐рдд рдХрд╛рд░реНрдпреЛрдВ, рд▓реИрдореНрдмреНрдбрд╛ рдФрд░ рдлрдВрдХреНрд╢рдирд▓рд░реНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдЖрдкрдХреЛ рд╕реНрдЯреНрд░реАрдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
#include <thread> void threadFunction() { // do smth } int main() { std::thread thr(threadFunction); thr.join(); return 0; }
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдереНрд░реЗрдб рдереНрд░реЗрдб рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рд╡рд╕реНрддреБ рд╣реИ рдЬрд┐рд╕рдореЗрдВ
threadFunction()
рдлрд╝рдВрдХреНрд╢рди рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдЧрд╛ред
join
рдХреЙрд▓ рдХреЙрд▓ рдереНрд░реЗрдб (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдореБрдЦреНрдп рдереНрд░реЗрдб) рдХреЛ
threadFunction()
рдпрд╛ рдмрд▓реНрдХрд┐
threadFunction()
рдЕрдкрдирд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рд╕реНрдЯреНрд░реАрдо рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдорд╛рди рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рдЕрдирджреЗрдЦрд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдХреЛрдИ рднреА рдкреИрд░рд╛рдореАрдЯрд░ рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
void threadFunction(int i, double d, const std::string &s) { std::cout << i << ", " << d << ", " << s << std::endl; } int main() { std::thread thr(threadFunction, 1, 2.34, "example"); thr.join(); return 0; }
рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдЖрдк рдХрд┐рд╕реА рднреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрдирдореЗрдВ рд╕реЗ рд╕рднреА рдХреЛ рдореВрд▓реНрдп рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдпрджрд┐ рдЖрдкрдХреЛ рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрджрд░реНрдн рджреНрд╡рд╛рд░рд╛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЙрдиреНрд╣реЗрдВ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдХреЗ рд░реВрдк рдореЗрдВ
std::ref
рдпрд╛
std::cref
рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:
void threadFunction(int &a) { a++; } int main() { int a = 1; std::thread thr(threadFunction, std::ref(a)); thr.join(); std::cout << a << std::endl; return 0; }
рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрдВрд╕реЛрд▓ рдХреЛ рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИ 2. рдпрджрд┐ рдЖрдк
std::ref
рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд╛ рдкрд░рд┐рдгрд╛рдо 1 рд╣реЛрдЧрд╛ред
join
рд╡рд┐рдзрд┐ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рдПрдХ рдФрд░, рд╕рдорд╛рди рд╡рд┐рдзрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП -
detach
ред
detach
рдЖрдкрдХреЛ рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдПрдХ рд╕реНрдЯреНрд░реАрдо рд╕реЗ рдЕрд▓рдЧ
detach
рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдЗрд╕реЗ рдкреГрд╖реНрдарднреВрдорд┐ рдмрдирд╛рдПрдВред
join
рдзрд╛рдЧреЗ рдЕрдм рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдХрд┐рдП рдЧрдП рдереНрд░реЗрдбреНрд╕ рдкрд░ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
int main() { std::thread thr(threadFunction); thr.detach(); return 0; }
рдпрд╣ рднреА рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпрджрд┐ рдХреЛрдИ рдереНрд░реЗрдб рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХрддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рдПрдХ рдХреЛрд╢рд┐рд╢-рдХреИрдЪ рдмреНрд▓реЙрдХ рджреНрд╡рд╛рд░рд╛ рдирд╣реАрдВ рдкрдХрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╛рдиреА рдирд┐рдореНрди рдХреЛрдб рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ (рдпрд╣ рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рдЗрд░рд╛рджрд╛ рдирд╣реАрдВ рд╣реИ: рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдкрдХрдбрд╝реЗ рдмрд┐рдирд╛):
try { std::thread thr1(threadFunction); std::thread thr2(threadFunction); thr1.join(); thr2.join(); } catch (const std::exception &ex) { std::cout << ex.what() << std::endl; }
рдереНрд░реЗрдбреНрд╕ рдХреЗ рдмреАрдЪ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЙрдиреНрд╣реЗрдВ рд╕реНрдЯреНрд░реАрдо рдлрд╝рдВрдХреНрд╢рдВрд╕ рдореЗрдВ рдкрдХрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХрд╣реАрдВ рд╕реНрдЯреЛрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рддрд╛рдХрд┐ рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рдЙрди рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рд╛рдкреНрдд рд╣реЛ рд╕рдХреЗред
std::mutex g_mutex; std::vector<std::exception_ptr> g_exceptions; void throw_function() { throw std::exception("something wrong happened"); } void threadFunction() { try { throw_function(); } catch (...) { std::lock_guard<std::mutex> lock(g_mutex); g_exceptions.push_back(std::current_exception()); } } int main() { g_exceptions.clear(); std::thread thr(threadFunction); thr.join(); for(auto &e: g_exceptions) { try { if(e != nullptr) std::rethrow_exception(e); } catch (const std::exception &e) { std::cout << e.what() << std::endl; } } return 0; }
рдЖрдЧреЗ рдмрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ
<thread>
std::this_thread
<thread>
рджреНрд╡рд╛рд░рд╛
std::this_thread
рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдХреБрдЫ рдЙрдкрдпреЛрдЧреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛
std::this_thread
:
- get_id : рд╡рд░реНрддрдорд╛рди рдереНрд░реЗрдб рдХреА рдЖрдИрдбреА рд▓реМрдЯрд╛рддрд╛ рд╣реИ
- рдкреИрджрд╛рд╡рд╛рд░ : рдЕрдиреНрдп рд╕реВрддреНрд░ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд╕реВрдЪрдХ рдХреЛ рдмрддрд╛рддрд╛ рд╣реИ, рд╕рдХреНрд░рд┐рдп рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреЗ рд╕рд╛рде рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
- sleep_for : рдПрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдЕрд╡рдзрд┐ рдХреЗ рд▓рд┐рдП рд╡рд░реНрддрдорд╛рди рдереНрд░реЗрдб рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рд░реЛрдХрддрд╛ рд╣реИ
- sleep_until : рд╡рд░реНрддрдорд╛рди рдереНрд░реЗрдб рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рддрдм рддрдХ рдХреЗ рд▓рд┐рдП рдмреНрд▓реЙрдХ рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╕рдордп рддрдХ рдкрд╣реБрдБрдЪ рди рдЬрд╛рдП
рдЕрд╡рд░реБрджреНрдз
рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдореБрдЭреЗ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
g_exceptions
рд╡реЗрдХреНрдЯрд░ рдХреА рдкрд╣реБрдВрдЪ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рдирд╛ рдерд╛ рдХрд┐ рдПрдХ рд╕рдордп рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдзрд╛рдЧрд╛ рдПрдХ рдирдпрд╛ рддрддреНрд╡ рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░ рд╕рдХреЗред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдФрд░ рдореНрдпреВрдЯреЗрдХреНрд╕ рдкрд░ рддрд╛рд▓рд╛ рд▓рдЧрд╛ рджрд┐рдпрд╛ред Mutex рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдХрд╛ рдореВрд▓ рддрддреНрд╡ рд╣реИ рдФрд░ C ++ 11 рдореЗрдВ рдЗрд╕реЗ
<mutex>
рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ 4 рд░реВрдкреЛрдВ рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
рдпрд╣рд╛рдБ
std::mutex
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ
std::mutex
,
get_id()
рдФрд░
sleep_for()
рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
#include <iostream> #include <chrono> #include <thread> #include <mutex> std::mutex g_lock; void threadFunction() { g_lock.lock(); std::cout << "entered thread " << std::this_thread::get_id() << std::endl; std::this_thread::sleep_for(std::chrono::seconds(rand()%10)); std::cout << "leaving thread " << std::this_thread::get_id() << std::endl; g_lock.unlock(); } int main() { srand((unsigned int)time(0)); std::thread t1(threadFunction); std::thread t2(threadFunction); std::thread t3(threadFunction); t1.join(); t2.join(); t3.join(); return 0; }
рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:
entered thread 10144 leaving thread 10144 entered thread 4188 leaving thread 4188 entered thread 3424 leaving thread 3424
рд╕рд╛рдорд╛рдиреНрдп рдбреЗрдЯрд╛ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ
lock
рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рд▓реЙрдХ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЗрд╕реЗ рдЕрдирд▓реЙрдХ рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рдЕрдирд▓реЙрдХ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдирд┐рдореНрди рдЙрджрд╛рд╣рд░рдг рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдереНрд░реЗрдб-рд╕реБрд░рдХреНрд╖рд┐рдд рдХрдВрдЯреЗрдирд░ (
std::vector
рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд
add()
addrange()
рдЬрд┐рд╕рдореЗрдВ рдХрдИ рддрддреНрд╡реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрддреНрд╡ рдФрд░
addrange()
рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП
add()
рддрд░реАрдХреЗ рд╣реИрдВред
рдиреЛрдЯ : рдФрд░ рдлрд┐рд░ рднреА рдпрд╣ рдХрдВрдЯреЗрдирд░ рдХрдИ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ
va_args
рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢рд╛рдорд┐рд▓ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛,
dump()
рд╡рд┐рдзрд┐ рдХрдВрдЯреЗрдирд░ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдПрдХ рд╕реНрдЯреИрдВрдб-рдЕрд▓реЛрди рдлрд╝рдВрдХреНрд╢рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдореНрдпреВрдЯреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдмреБрдирд┐рдпрд╛рджреА рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рджрд┐рдЦрд╛рдирд╛ рд╣реИ, рдФрд░ рдПрдХ рдкреВрд░реНрдг, рддреНрд░реБрдЯрд┐ рд░рд╣рд┐рдд, рдереНрд░реЗрдб-рд╕реБрд░рдХреНрд╖рд┐рдд рдХрдВрдЯреЗрдирд░ рдирд╣реАрдВ рдмрдирд╛рдирд╛ рд╣реИред
template <typename T> class container { std::mutex _lock; std::vector<T> _elements; public: void add(T element) { _lock.lock(); _elements.push_back(element); _lock.unlock(); } void addrange(int num, ...) { va_list arguments; va_start(arguments, num); for (int i = 0; i < num; i++) { _lock.lock(); add(va_arg(arguments, T)); _lock.unlock(); } va_end(arguments); } void dump() { _lock.lock(); for(auto e: _elements) std::cout << e << std::endl; _lock.unlock(); } }; void threadFunction(container<int> &c) { c.addrange(3, rand(), rand(), rand()); } int main() { srand((unsigned int)time(0)); container<int> cntr; std::thread t1(threadFunction, std::ref(cntr)); std::thread t2(threadFunction, std::ref(cntr)); std::thread t3(threadFunction, std::ref(cntr)); t1.join(); t2.join(); t3.join(); cntr.dump(); return 0; }
рдЬрдм рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ
рдЧрддрд┐рд░реЛрдз рдЙрддреНрдкрдиреНрди рд╣реЛрдЧрд╛ (рдЧрддрд┐рд░реЛрдз, рдпрд╛рдиреА рдПрдХ рдЕрд╡рд░реБрджреНрдз рдзрд╛рдЧрд╛ рдЕрднреА рднреА рдЗрдВрддрдЬрд╛рд░ рдХрд░реЗрдЧрд╛)ред рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдХрдВрдЯреЗрдирд░ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ рд░рд┐рд▓реАрдЬрд╝ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХрдИ рдмрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ (рдХреЙрд▓
unlock
), рдЬреЛ рдЕрд╕рдВрднрд╡ рд╣реИред рдпрд╣рд╛рдБ
std::recursive_mutex
рджреГрд╢реНрдп рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ рдХрдИ рдмрд╛рд░ рдПрдХ рд╣реА рдореНрдпреВрдЯреЗрдХреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдПрдХ рдореНрдпреВрдЯреЗрдХреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдзрд┐рдХрддрдо рдорд╛рддреНрд░рд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдпрд╣ рд░рд╛рд╢рд┐ рддрдХ рдкрд╣реБрдВрдЪ рдЬрд╛рддреА рд╣реИ, рддреЛ
lock
рдЕрдкрд╡рд╛рдж
std :: system_error рдлреЗрдВрдХ
рджреЗрдЧрд╛ ред рдЗрд╕рд▓рд┐рдП, рдКрдкрд░ рджрд┐рдП рдЧрдП рдХреЛрдб рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди (
addrange()
рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛
addrange()
рддрд╛рдХрд┐
lock
рдФрд░
unlock
рдмреБрд▓рд╛рдпрд╛ рди рдЬрд╛рдП), mutex рдХреЛ
std::recursive_mutex
рд╕реЗ рдмрджрд▓рдирд╛ рд╣реИред
template <typename T> class container { std::recursive_mutex _lock;
рдЕрдм, рдХрд╛рд░реНрдпрдХреНрд░рдо рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:
6334 18467 41 6334 18467 41 6334 18467 41
рдЖрдкрдиреЗ рд╢рд╛рдпрдж рджреЗрдЦрд╛ рдХрд┐ рдЬрдм рдЖрдк
threadFunction()
, рддреЛ рд╕рдорд╛рди рд╕рдВрдЦреНрдпрд╛рдПрдВ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИрдВред рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди
void srand (unsigned int seed);
рдХреЗрд╡рд▓ рдореБрдЦреНрдп рдзрд╛рдЧреЗ рдХреЗ рд▓рд┐рдП
seed
рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИред рдЕрдиреНрдп рдереНрд░реЗрдбреНрд╕ рдореЗрдВ, рдЫрджреНрдо рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдЬрдирд░реЗрдЯрд░ рдХреЛ рдЖрд░рдВрднреАрдХреГрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╣рд░ рдмрд╛рд░ рд╕рдорд╛рди рд╕рдВрдЦреНрдпрд╛рдПрдВ рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛рддреА рд╣реИрдВред
рд╕реНрдкрд╖реНрдЯ рд▓реЙрдХрд┐рдВрдЧ рдФрд░ рдЕрдирд▓реЙрдХрд┐рдВрдЧ рд╕реЗ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рдереНрд░реЗрдб рдХреЛ рдЕрдирд▓реЙрдХ рдХрд░рдирд╛ рднреВрд▓ рдЬрд╛рддреЗ рд╣реИрдВ рдпрд╛ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рддрд╛рд▓реЗ рдХрд╛ рдПрдХ рдЧрд▓рдд рдХреНрд░рдо рд╣реИ - рдпрд╣ рд╕рдм рдЧрддрд┐рд░реЛрдз рдХрд╛ рдХрд╛рд░рдг рд╣реЛрдЧрд╛ред Std рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдХрдХреНрд╖рд╛рдПрдВ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
рд░реИрдкрд░ рдХрдХреНрд╖рд╛рдПрдВ рдЖрдкрдХреЛ
рдЖрд░рдПрдЖрдИ рд╢реИрд▓реА рдореЗрдВ рдПрдХ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд▓реЙрдХрд┐рдВрдЧ рдФрд░ рдПрдХрд▓ рдмреНрд▓реЙрдХ рдХреЗ рднреАрддрд░ рдЕрдирд▓реЙрдХ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рд▓рдЧрд╛рддрд╛рд░ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИрдВред рдпреЗ рд╡рд░реНрдЧ рд╣реИрдВ:
- рд▓реЙрдХ_рдЧрд╛рд░реНрдб : рдЬрдм рдХреЛрдИ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╡рд╣ рдореНрдпреВрдЯреЗрдХреНрд╕ (
lock()
рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ lock()
рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЬрдм рдСрдмреНрдЬреЗрдХреНрдЯ рдирд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдореНрдпреВрдЯреЗрдХреНрд╕ ( unlock()
рдХреЙрд▓ рдХрд░рдХреЗ) рдЬрд╛рд░реА рдХрд░рддрд╛ рд╣реИред - рдЕрджреНрд╡рд┐рддреАрдп_рд▓реЙрдХ : рд▓реЙрдХ_рдЧрд╛рд░реНрдб рдХреЗ рд╡рд┐рдкрд░реАрдд, рдпрд╣ рдЖрд╕реНрдердЧрд┐рдд рд▓реЙрдХрд┐рдВрдЧ, рдЕрд╕реНрдерд╛рдпреА рд▓реЙрдХрд┐рдВрдЧ, рдкреБрдирд░рд╛рд╡рд░реНрддреА рд▓реЙрдХрд┐рдВрдЧ рдФрд░ рд╕рд╢рд░реНрдд рдЪрд░ рдХреЗ рдЙрдкрдпреЛрдЧ рдХрд╛ рднреА рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ
рдЗрд╕реЗ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП, рд╣рдо рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдХрдВрдЯреЗрдирд░ рд╡рд░реНрдЧ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
template <typename T> class container { std::recursive_mutex _lock; std::vector<T> _elements; public: void add(T element) { std::lock_guard<std::recursive_mutex> locker(_lock); _elements.push_back(element); } void addrange(int num, ...) { va_list arguments; va_start(arguments, num); for (int i = 0; i < num; i++) { std::lock_guard<std::recursive_mutex> locker(_lock); add(va_arg(arguments, T)); } va_end(arguments); } void dump() { std::lock_guard<std::recursive_mutex> locker(_lock); for(auto e: _elements) std::cout << e << std::endl; } };
рдпрд╣ рддрд░реНрдХ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐
dump()
рд╡рд┐рдзрд┐ рд╕реНрдерд┐рд░ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХрдВрдЯреЗрдирд░ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИред рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдФрд░ рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ:
'std::lock_guard<_Mutex>::lock_guard(_Mutex &)' : cannot convert parameter 1 from 'const std::recursive_mutex' to 'std::recursive_mutex &'
рдореНрдпреВрдЯреЗрдХреНрд╕ (рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд░реВрдк рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛) рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдпрд╣ рдЧреИрд░-рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ
lock()
рдФрд░
unlock()
ред рдЗрд╕ рдкреНрд░рдХрд╛рд░,
lock_guard
рддрд░реНрдХ рд╕реНрдерд┐рд░ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ
mutable
рдмрдирд╛рдирд╛ рд╣реИ, рдлрд┐рд░ рдХреЙрдиреНрд╕реНрдЯреЗрдмрд▓ рдХреЛ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдпрд╣ рдЖрдкрдХреЛ рдирд┐рд░рдВрддрд░ рдХрд╛рд░реНрдпреЛрдВ рд╕реЗ рд░рд╛рдЬреНрдп рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред
template <typename T> class container { mutable std::recursive_mutex _lock; std::vector<T> _elements; public: void dump() const { std::lock_guard<std::recursive_mutex> locker(_lock); for(auto e: _elements) std::cout << e << std::endl; } };
рдЖрд╡рд░рдг рд╡рд░реНрдЧреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд▓реЙрдХрд┐рдВрдЧ рдиреАрддрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ:
defer_lock
type defer_lock_t
: рдореНрдпреВрдЯреЗрдХреНрд╕ рдкреНрд░рд╛рдкреНрдд рди рдХрд░реЗрдВtry_to_lock
type try_to_lock_t
: рд▓реЙрдХ рдХрд┐рдП рдмрд┐рдирд╛ рдореНрдпреВрдЯреЗрдХреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВadopt_lock
type рдХреЛ adopt_lock_t
: рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреЙрд▓рд┐рдВрдЧ рдереНрд░реЗрдб рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдореНрдпреВрдЯреЗрдХреНрд╕ рд╣реИ
рдЙрдиреНрд╣реЗрдВ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
struct defer_lock_t { }; struct try_to_lock_t { }; struct adopt_lock_t { }; constexpr std::defer_lock_t defer_lock = std::defer_lock_t(); constexpr std::try_to_lock_t try_to_lock = std::try_to_lock_t(); constexpr std::adopt_lock_t adopt_lock = std::adopt_lock_t();
рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЗ рд▓рд┐рдП "рд░реИрдкрд░" рдХреЗ рдЕрд▓рд╛рд╡рд╛,
std
рдПрдХ рдпрд╛ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ рд▓реЙрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рддрд░реАрдХреЗ рднреА рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:
- рд▓реЙрдХ : рдбреЗрдбрд▓реЙрдХ рдкрд░рд┐рд╣рд╛рд░ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо (
lock()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ lock()
, try_lock()
рдФрд░ unlock()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ рд▓реЙрдХ рдХрд░рддрд╛ рд╣реИ - try_lock : рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЛ рдЙрд╕ рдХреНрд░рдо рдореЗрдВ рдмреНрд▓реЙрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╡реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдП рдЧрдП рдереЗ
рдпрд╣рд╛рдВ рдЧрддрд┐рд░реЛрдз рдХрд╛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдг рд╣реИ: рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рддрддреНрд╡реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХрдВрдЯреЗрдирд░ рд╣реИ рдФрд░ рдПрдХ
exchange()
рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рд╡рд┐рднрд┐рдиреНрди рдХрдВрдЯреЗрдирд░реЛрдВ рдХреЗ рджреЛ рддрддреНрд╡реЛрдВ рдХреЛ рд╕реНрд╡реИрдк рдХрд░рддрд╛ рд╣реИред рдереНрд░реЗрдб рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП, рдлрд╝рдВрдХреНрд╢рди рдЗрди рдХрдВрдЯреЗрдирд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдХрдВрдЯреЗрдирд░ рд╕реЗ рдЬреБрдбрд╝рд╛ рдореНрдпреВрдЯреЗрдХреНрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред
template <typename T> class container { public: std::mutex _lock; std::set<T> _elements; void add(T element) { _elements.insert(element); } void remove(T element) { _elements.erase(element); } }; void exchange(container<int> &c1, container<int> &c2, int value) { c1._lock.lock(); std::this_thread::sleep_for(std::chrono::seconds(1));
рдорд╛рди рд▓реЗрдВ рдХрд┐ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд╣рд▓реЗ рдзрд╛рдЧреЗ рд╕реЗ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдереНрд░реЗрдбреНрд╕ рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рддрддреНрд╡ рдХреЛ 1 рдХрдВрдЯреЗрдирд░ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ 2 рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рджреВрд╕рд░реЗ рдзрд╛рдЧреЗ рд╕реЗ, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рддрддреНрд╡ рдХреЛ 2 рдХрдВрдЯреЗрдирд░реЛрдВ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ 1. рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдЧрддрд┐рд░реЛрдз рдкреИрджрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ (рдпрджрд┐ рдереНрд░реЗрдб рдХрд╛ рд╕рдВрджрд░реНрдн рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ) рдПрдХ рдзрд╛рдЧреЗ рд╕реЗ рджреВрд╕рд░реЗ рддрдХ, рдкрд╣рд▓реЗ рдмреНрд▓реЙрдХ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж)ред
int main() { srand((unsigned int)time(NULL)); container<int> cntr1; cntr1.add(1); cntr1.add(2); cntr1.add(3); container<int> cntr2; cntr2.add(4); cntr2.add(5); cntr2.add(6); std::thread t1(exchange, std::ref(cntr1), std::ref(cntr2), 3); std::thread t2(exchange, std::ref(cntr2), std::ref(cntr1), 6); t1.join(); t2.join(); return 0; }
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк
std::lock
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рд╕реБрд░рдХреНрд╖рд┐рдд (рдЧрддрд┐рд░реЛрдз рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ) рддрд░реАрдХреЗ рд╕реЗ рд▓реЙрдХрд┐рдВрдЧ рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрддрд╛ рд╣реИ:
void exchange(container<int> &c1, container<int> &c2, int value) { std::lock(c1._lock, c2._lock); c1.remove(value); c2.add(value); c1._lock.unlock(); c2._lock.unlock(); }
рдЬрд╛рд░реА :
рд╕рд╢рд░реНрдд рдЪрд░