TGViewer
C/C++ | Вопросы собесов C/C++ | Вопросы собесов @easy_c_plus · 4.2K subscribers
Post #2424 639
🤔 Что будет если вызвать дважды lock()?

Если вызвать дважды lock() на одном и том же объекте std::mutex из одного и того же потока, это приведет к взаимной блокировке (deadlock). Это происходит потому, что после первого вызова lock() мьютекс уже будет заблокирован данным потоком, и второй вызов lock() будет ожидать освобождения мьютекса, что никогда не произойдет, так как поток уже заблокировал мьютекс.
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void threadFunction() {
mtx.lock(); // Первый вызов lock()
std::cout << "Locked once" << std::endl;

// Попытка повторного захвата того же мьютекса приведет к взаимной блокировке
mtx.lock(); // Второй вызов lock() - Deadlock
std::cout << "Locked twice" << std::endl;

mtx.unlock();
mtx.unlock();
}

int main() {
std::thread t(threadFunction);
t.join();

return 0;
}


🚩Как избежать взаимной блокировки

🟠Использование `std::recursive_mutex`: Этот тип мьютекса позволяет одному и тому же потоку захватывать мьютекс несколько раз без блокировки. Но следует использовать его осторожно, так как он может скрывать логические ошибки в коде.
#include <iostream>
#include <thread>
#include <mutex>

std::recursive_mutex rec_mtx;

void threadFunction() {
rec_mtx.lock(); // Первый вызов lock()
std::cout << "Locked once" << std::endl;

rec_mtx.lock(); // Второй вызов lock()
std::cout << "Locked twice" << std::endl;

rec_mtx.unlock();
rec_mtx.unlock();
}

int main() {
std::thread t(threadFunction);
t.join();

return 0;
}


🟠Использование `std::unique_lock` или `std::lock_guard`: Эти обертки автоматически управляют блокировкой и разблокировкой мьютекса, обеспечивая корректное использование мьютексов.
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void threadFunction() {
std::lock_guard<std::mutex> lock(mtx); // Автоматическая блокировка
std::cout << "Locked once" << std::endl;

// Повторный вызов lock() не требуется, так как lock_guard управляет мьютексом
}

int main() {
std::thread t(threadFunction);
t.join();

return 0;
}


🟠Проверка состояния мьютекса с помощью `try_lock()`: Метод try_lock() пытается захватить мьютекс и возвращает false, если мьютекс уже захвачен, что предотвращает взаимную блокировку.
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void threadFunction() {
if (mtx.try_lock()) { // Попытка захвата мьютекса
std::cout << "Locked once" << std::endl;

if (mtx.try_lock()) { // Попытка повторного захвата
std::cout << "Locked twice" << std::endl;
mtx.unlock();
}

mtx.unlock();
}
}

int main() {
std::thread t(threadFunction);
t.join();

return 0;


Ставь 👍 и забирай 📚 Базу знаний
More from @easy_c_plus
  1. Oct 12, 2026🤔 Какая сложность поиска в set и unordered_set? Контейнеры set и unordered_set представля…
  2. Oct 11, 2026Post #2563
  3. Oct 11, 2026🤔 Как проверять равенство двух float? Равенство двух float проверяется с учётом допустимо…
  4. Oct 11, 2026🤔 Расскажи о истории умных указателей История умных указателей (smart pointers) в C++ свя…
  5. Oct 10, 2026🤔 Зачем нужен виртуальный деструктор? Виртуальный деструктор необходим, когда класс предп…
  6. Oct 10, 2026🤔 Что знаешь про гарантии безопасности исключений? Гарантии безопасности исключений (Exce…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →