Согласно cppreference, создание std::lock_guard
с параметром std::mutex
вызывает метод lock()
из этого mutex
.
Согласно cplusplus относительно метода mutex
lock()
:
Если мьютекс заблокирован другим потоком, выполнение вызывающего потока блокируется до тех пор, пока не будет разблокировано другим потоком...
Я не уверен, правильно ли сформулирован главный вопрос, поэтому я поместил его в контекст приведенного ниже кода.
Я хотел проверить это и посмотреть, действительно ли вызывающий поток ожидает разблокировки вместо прекращения выполнения своего вызываемого объекта (например, функции, функтора, лямбды) и/или выдает исключение. В следующем коде есть два потока t1
и t2
, каждый из которых создан с помощью указателя на одну и ту же функцию foo
. Каждый вызов foo
будет sleep_for
через определенное время, определяемое unsigned
параметром num
foo
, перед выполнением кода, защищенного блокировкой. Сам код, защищенный блокировкой, содержит еще один период sleep_for
, чтобы сделать любой заблокированный период выполнения более очевидным:
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
std::mutex m;
void foo(unsigned num) {
std::this_thread::sleep_for(std::chrono::milliseconds(num * 10));
std::lock_guard<std::mutex> guard(m);
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
std::cout << num << std::endl;
}
int main() {
std::thread t1(foo, 10);
std::thread t2(foo, 5);
t1.join();
t2.join();
}
Выход консоли:
5
10
Для вывода 5
требуется около/не менее 3,05 секунд. Для вывода 10
требуется около/по крайней мере еще 3 секунды. Это означает, что t2
сначала выполняет защищенный код, поскольку у него меньше времени ожидания до блокировки mutex
.
Я предполагаю, что когда вызов foo
из потока t1
доходит до строки lock_guard
и обнаруживает, что mutex
уже заблокирован t2
, t1
не прекращает выполнение и не генерирует исключение. t1
просто ждет, пока его разблокируют.
Как часто std::mutex::lock()
или std::lock_guard
делают эту проверку для разблокировки? Насколько дорогая проверка? Проверка реализована следующим образом?
while (some_mutex.try_lock() == false) {
std::this_thread::sleep_for(std::chrono::milliseconds(1))
}
// execute lock-protected code