Какие знаешь мьютексы
1️⃣ Как кратко ответить
В C++ стандартная библиотека предоставляет несколько типов мьютексов: std::mutex, std::timed_mutex, std::recursive_mutex, std::recursive_timed_mutex, std::shared_mutex и std::shared_timed_mutex. Каждый из них имеет свои особенности и предназначен для различных сценариев синхронизации потоков.
2️⃣ Подробное объяснение темы
Мьютексы (от англ. "mutex" — mutual exclusion) — это механизмы синхронизации, которые используются для предотвращения одновременного доступа нескольких потоков к общим ресурсам. В C++ стандартная библиотека предоставляет несколько типов мьютексов, каждый из которых имеет свои особенности и предназначен для различных сценариев.
-
std::mutexЭто базовый тип мьютекса, который предоставляет простейший механизм блокировки. Он используется для защиты критических секций, чтобы только один поток мог выполнять код в этой секции в любой момент времени.
#include <iostream> #include <thread> #include <mutex> std::mutex mtx; void print_message(const std::string& message) { mtx.lock(); // Блокируем мьютекс std::cout << message << std::endl; mtx.unlock(); // Разблокируем мьютекс } int main() { std::thread t1(print_message, "Hello from thread 1"); std::thread t2(print_message, "Hello from thread 2"); t1.join(); t2.join(); return 0; }В этом примере
std::mutexиспользуется для синхронизации доступа кstd::cout, чтобы избежать одновременного вывода из нескольких потоков. -
std::timed_mutexЭтот мьютекс позволяет задавать время ожидания при попытке захвата блокировки. Если мьютекс не может быть захвачен в течение заданного времени, поток может продолжить выполнение без блокировки.
#include <iostream> #include <thread> #include <mutex> #include <chrono> std::timed_mutex tmtx; void try_lock_for_example() { if (tmtx.try_lock_for(std::chrono::milliseconds(100))) { std::cout << "Lock acquired" << std::endl; tmtx.unlock(); } else { std::cout << "Lock not acquired" << std::endl; } } int main() { std::thread t1(try_lock_for_example); std::thread t2(try_lock_for_example); t1.join(); t2.join(); return 0; }Здесь
try_lock_forпытается захватить мьютекс в течение 100 миллисекунд. -
std::recursive_mutexЭтот мьютекс позволяет одному и тому же потоку захватывать мьютекс несколько раз без блокировки. Это полезно в случаях, когда функция вызывает саму себя (рекурсия) и требуется синхронизация.
#include <iostream> #include <thread> #include <mutex> std::recursive_mutex rmtx; void recursive_function(int count) { if (count <= 0) return; rmtx.lock(); std::cout << "Recursion level: " << count << std::endl; recursive_function(count - 1); rmtx.unlock(); } int main() { std::thread t1(recursive_function, 3); t1.join(); return 0; }В этом примере
std::recursive_mutexпозволяет функцииrecursive_functionзахватывать мьютекс несколько раз. -
std::recursive_timed_mutexЭто комбинация
std::recursive_mutexиstd::timed_mutex, позволяющая рекурсивное захватывание с возможностью задания времени ожидания. -
std::shared_mutexЭтот мьютекс позволяет нескольким потокам одновременно читать данные, но только одному потоку записывать. Это полезно для сценариев, где чтение данных происходит чаще, чем запись.
#include <iostream> #include <thread> #include <shared_mutex> std::shared_mutex smtx; int shared_data = 0; void read_data() { smtx.lock_shared(); std::cout << "Read data: " << shared_data << std::endl; smtx.unlock_shared(); } void write_data(int value) { smtx.lock(); shared_data = value; std::cout << "Wrote data: " << shared_data << std::endl; smtx.unlock(); } int main() { std::thread t1(read_data); std::thread t2(write_data, 42); t1.join(); t2.join(); return 0; }В этом примере
std::shared_mutexпозволяет нескольким потокам одновременно читатьshared_data, но только одному потоку записывать. -
std::shared_timed_mutexЭто расширение
std::shared_mutex, которое добавляет возможность задания времени ожидания для захвата блокировки.
Каждый из этих мьютексов предоставляет уникальные возможности для управления доступом к ресурсам в многопоточных приложениях. Выбор подходящего мьютекса зависит от конкретных требований к синхронизации в вашем приложении.
🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!
Подписаться