Почему блокировка std:: mutex не блокирует поток
Я написал следующий код, чтобы проверить мое понимание std::mutex
int main() {
mutex m;
m.lock();
m.lock(); // expect to block the thread
}
А потом я получил system_error: device or resource busy
. Разве не второй m.lock()
должен блокировать поток?
Ответы
Ответ 1
От std::mutex
:
Вызывающий поток не должен владеть мьютексом до блокировки вызова или try_lock.
и std::mutex::lock
:
Если блокировка вызывается потоком, который уже владеет мьютексом, программа может зайти в тупик. В качестве альтернативы, если реализация может обнаружить тупик, может наблюдаться условие ошибки resource_deadlock_would_occur.
и предложение исключений:
Выбрасывает std:: system_error при возникновении ошибок, включая ошибки из базовой операционной системы, которые не позволят блокировке выполнить свои спецификации. Мьютекс не заблокирован в случае выброса любого исключения.
Поэтому он не должен блокировать поток. На вашей платформе реализация, похоже, обнаруживает, что поток уже является владельцем блокировки и создает исключение. Это может не произойти на других платформах, как указано в описаниях.
Ответ 2
Не второй m.lock()
должен блокировать поток?
Нет, он дает поведение undefined. Второй m.lock()
нарушает это требование:
С++ 11 30.4.1.2/7 Требуется: Если m имеет тип std::mutex
или std::timed_mutex
, вызывающий поток не имеет мьютекс.
Похоже, ваша реализация может обнаружить, что вызывающий поток владеет мьютексом и дает ошибку; другие могут блокироваться бесконечно или потерпеть неудачу другими способами.
Ответ 3
(std::mutex
не упоминался в вопросе, когда я написал этот ответ.)
Это зависит от библиотеки мьютексов и типа мьютекса, которые вы используете, - вы не сказали нам. Некоторые системы предоставляют "рекурсивный мьютекс", который разрешается вызывать несколько раз, как это происходит, только если это происходит из того же потока (тогда у вас должно быть соответствующее количество разблокировок, прежде чем другой поток сможет его заблокировать), другие библиотеки считают это ошибкой и может потерпеть неудачу изящно (как у вас) или иметь поведение undefined.